From: John.C.Harrison@Intel.com
To: Intel-GFX@Lists.FreeDesktop.Org
Subject: [PATCH v6 24/34] drm/i915: Added scheduler queue throttling by DRM file handle
Date: Fri, 6 May 2016 14:19:31 +0100 [thread overview]
Message-ID: <1462540771-22968-1-git-send-email-John.C.Harrison@Intel.com> (raw)
In-Reply-To: <1461172435-4256-25-git-send-email-John.C.Harrison@Intel.com>
From: John Harrison <John.C.Harrison@Intel.com>
The scheduler decouples the submission of batch buffers to the driver
from their subsequent submission to the hardware. This means that an
application which is continuously submitting buffers as fast as it can
could potentialy flood the driver. To prevent this, the driver now
tracks how many buffers are in progress (queued in software or
executing in hardware) and limits this to a given (tunable) number. If
this number is exceeded then the queue to the driver will return
EAGAIN and thus prevent the scheduler's queue becoming arbitrarily
large.
v3: Added a missing decrement of the file queue counter.
v4: Updated a comment.
v5: Updated due to changes to earlier patches in series - removing
forward declarations and white space. Also added some documentation.
[Joonas Lahtinen]
v6: Updated to newer nightly (lots of ring -> engine renaming).
Replace the simple 'return to userland when full' scheme with a 'sleep
on request' scheme. The former could lead to the busy polling and
wasting lots of CPU time as user land continuously retried the execbuf
IOCTL in a tight loop. Now the driver will sleep (without holding the
mutex lock) on the oldest request outstanding for that file and then
automatically retry. This is closer to the pre-scheduler behaviour of
stalling on a full ring buffer.
v6.1: Moved throttle point to later common location. Required for a
subsequent patch that needs the engine to have been determined already.
For: VIZ-1587
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 +
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 +
drivers/gpu/drm/i915/i915_scheduler.c | 118 +++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_scheduler.h | 2 +
4 files changed, 126 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e9aaacc..25b8fd6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -376,6 +376,8 @@ struct drm_i915_file_private {
} rps;
unsigned int bsd_ring;
+
+ u32 scheduler_queue_length;
};
/* Used by dp and fdi links */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a08638a..5a674ad 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1538,6 +1538,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
dispatch_flags |= I915_DISPATCH_RS;
}
+ /* Throttle batch requests per device file */
+ if (i915_scheduler_file_queue_wait(file))
+ return -EAGAIN;
+
intel_runtime_pm_get(dev_priv);
ret = i915_mutex_lock_interruptible(dev);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index a3a7a82..3569ddd 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -80,6 +80,7 @@ int i915_scheduler_init(struct drm_device *dev)
scheduler->priority_level_bump = 50;
scheduler->priority_level_preempt = 900;
scheduler->min_flying = 2;
+ scheduler->file_queue_max = 64;
dev_priv->scheduler = scheduler;
@@ -496,6 +497,28 @@ static int i915_scheduler_submit_unlocked(struct intel_engine_cs *engine)
return ret;
}
+/**
+ * i915_scheduler_file_queue_inc - Increment the file's request queue count.
+ * @file: File object to process.
+ */
+static void i915_scheduler_file_queue_inc(struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+
+ file_priv->scheduler_queue_length++;
+}
+
+/**
+ * i915_scheduler_file_queue_dec - Decrement the file's request queue count.
+ * @file: File object to process.
+ */
+static void i915_scheduler_file_queue_dec(struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+
+ file_priv->scheduler_queue_length--;
+}
+
static void i915_generate_dependencies(struct i915_scheduler *scheduler,
struct i915_scheduler_queue_entry *node,
uint32_t engine)
@@ -675,6 +698,8 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
list_add_tail(&node->link, &scheduler->node_queue[engine->id]);
+ i915_scheduler_file_queue_inc(node->params.file);
+
not_flying = i915_scheduler_count_flying(scheduler, engine) <
scheduler->min_flying;
@@ -871,6 +896,12 @@ static bool i915_scheduler_remove(struct i915_scheduler *scheduler,
/* Strip the dependency info while the mutex is still locked */
i915_scheduler_remove_dependent(scheduler, node);
+ /* Likewise clean up the file pointer. */
+ if (node->params.file) {
+ i915_scheduler_file_queue_dec(node->params.file);
+ node->params.file = NULL;
+ }
+
continue;
}
@@ -963,6 +994,92 @@ void i915_scheduler_work_handler(struct work_struct *work)
i915_scheduler_process_work(engine);
}
+/**
+ * i915_scheduler_file_queue_wait - Waits for space in the per file queue.
+ * @file: File object to process.
+ * This allows throttling of applications by limiting the total number of
+ * outstanding requests to a specified level. Once that limit is reached,
+ * this call will stall waiting on the oldest outstanding request. If it can
+ * not stall for any reason it returns true to mean that the queue is full
+ * and no more requests should be accepted.
+ */
+bool i915_scheduler_file_queue_wait(struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_private *dev_priv = file_priv->dev_priv;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+ struct drm_i915_gem_request *req;
+ struct i915_scheduler_queue_entry *node;
+ unsigned reset_counter;
+ int ret;
+ struct intel_engine_cs *engine;
+
+ if (file_priv->scheduler_queue_length < scheduler->file_queue_max)
+ return false;
+
+ do {
+ spin_lock_irq(&scheduler->lock);
+
+ /*
+ * Find the first (i.e. oldest) request for this file. In the
+ * case where an app is using multiple engines, this search
+ * might be skewed by engine. However, worst case is an app has
+ * queued ~60 requests to a high indexed engine and then one
+ * request to a low indexed engine. In such a case, the driver
+ * will wait for longer than necessary but operation will
+ * still be correct and that case is not rare enough to add
+ * jiffy based inter-engine checks.
+ */
+ req = NULL;
+ for_each_engine(engine, dev_priv) {
+ for_each_scheduler_node(node, engine->id) {
+ if (I915_SQS_IS_COMPLETE(node))
+ continue;
+
+ if (node->params.file != file)
+ continue;
+
+ req = node->params.request;
+ break;
+ }
+
+ if (req)
+ break;
+ }
+
+ if (!req) {
+ spin_unlock_irq(&scheduler->lock);
+ return false;
+ }
+
+ i915_gem_request_reference(req);
+
+ spin_unlock_irq(&scheduler->lock);
+
+ ret = i915_gem_check_wedge(&dev_priv->gpu_error, false);
+ if (ret)
+ goto err_unref;
+
+ reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
+
+ ret = __i915_wait_request(req, reset_counter,
+ I915_WAIT_REQUEST_INTERRUPTIBLE, NULL, NULL);
+ if (ret)
+ goto err_unref;
+
+ /* Make sure the request's resources actually get cleared up */
+ i915_scheduler_process_work(req->engine);
+
+ i915_gem_request_unreference(req);
+ } while(file_priv->scheduler_queue_length >= scheduler->file_queue_max);
+
+ return false;
+
+err_unref:
+ i915_gem_request_unreference(req);
+ return true;
+}
+
static int i915_scheduler_submit_max_priority(struct intel_engine_cs *engine,
bool is_locked)
{
@@ -1185,6 +1302,7 @@ void i915_scheduler_closefile(struct drm_device *dev, struct drm_file *file)
node->status,
engine->name);
+ i915_scheduler_file_queue_dec(node->params.file);
node->params.file = NULL;
}
}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 4e7c0a7..5c33c83 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -94,6 +94,7 @@ struct i915_scheduler {
int32_t priority_level_bump;
int32_t priority_level_preempt;
uint32_t min_flying;
+ uint32_t file_queue_max;
};
/* Flag bits for i915_scheduler::flags */
@@ -116,5 +117,6 @@ int i915_scheduler_flush(struct intel_engine_cs *engine, bool is_locked);
int i915_scheduler_flush_stamp(struct intel_engine_cs *engine,
unsigned long stamp, bool is_locked);
bool i915_scheduler_is_mutex_required(struct drm_i915_gem_request *req);
+bool i915_scheduler_file_queue_wait(struct drm_file *file);
#endif /* _I915_SCHEDULER_H_ */
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2016-05-06 13:20 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-20 17:13 [PATCH v6 00/34] GPU scheduler for i915 driver John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 01/34] drm/i915: Add total count to context status debugfs output John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 02/34] drm/i915: Prelude to splitting i915_gem_do_execbuffer in two John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 03/34] drm/i915: Split i915_dem_do_execbuffer() in half John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 04/34] drm/i915: Cache request pointer in *_submission_final() John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 05/34] drm/i915: Re-instate request->uniq because it is extremely useful John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 06/34] drm/i915: Start of GPU scheduler John.C.Harrison
2016-06-10 16:24 ` Tvrtko Ursulin
2016-04-20 17:13 ` [PATCH v6 07/34] drm/i915: Disable hardware semaphores when GPU scheduler is enabled John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 08/34] drm/i915: Force MMIO flips when scheduler enabled John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 09/34] drm/i915: Added scheduler hook when closing DRM file handles John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 10/34] drm/i915: Added scheduler hook into i915_gem_request_notify() John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 11/34] drm/i915: Added deferred work handler for scheduler John.C.Harrison
2016-06-10 16:29 ` Tvrtko Ursulin
2016-04-20 17:13 ` [PATCH v6 12/34] drm/i915: Redirect execbuffer_final() via scheduler John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 13/34] drm/i915: Keep the reserved space mechanism happy John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 14/34] drm/i915: Added tracking/locking of batch buffer objects John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 15/34] drm/i915: Hook scheduler node clean up into retire requests John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 16/34] drm/i915: Added scheduler support to __wait_request() calls John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 17/34] drm/i915: Added scheduler support to page fault handler John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 18/34] drm/i915: Added scheduler flush calls to ring throttle and idle functions John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 19/34] drm/i915: Add scheduler hook to GPU reset John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 20/34] drm/i915: Added a module parameter to allow the scheduler to be disabled John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 21/34] drm/i915: Support for 'unflushed' ring idle John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 22/34] drm/i915: Defer seqno allocation until actual hardware submission time John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 23/34] drm/i915: Added trace points to scheduler John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 24/34] drm/i915: Added scheduler queue throttling by DRM file handle John.C.Harrison
2016-05-06 13:19 ` John.C.Harrison [this message]
2016-04-20 17:13 ` [PATCH v6 25/34] drm/i915: Added debugfs interface to scheduler tuning parameters John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 26/34] drm/i915: Add early exit to execbuff_final() if insufficient ring space John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 27/34] drm/i915: Added scheduler statistic reporting to debugfs John.C.Harrison
2016-05-06 13:21 ` John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 28/34] drm/i915: Add scheduler support functions for TDR John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 29/34] drm/i915: Enable GPU scheduler by default John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 30/34] drm/i915: Add scheduling priority to per-context parameters John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 31/34] drm/i915: Add support for retro-actively banning batch buffers John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 32/34] drm/i915: Allow scheduler to manage inter-ring object synchronisation John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 33/34] drm/i915: Added debug state dump facilities to scheduler John.C.Harrison
2016-04-20 17:13 ` [PATCH v6 34/34] drm/i915: Scheduler state dump via debugfs John.C.Harrison
2016-04-20 17:13 ` [PATCH 1/1] drm/i915: Add wrapper for context priority interface John.C.Harrison
2016-04-20 17:13 ` [PATCH 1/2] igt/gem_ctx_param_basic: Updated to support scheduler " John.C.Harrison
2016-04-20 17:13 ` [PATCH 2/2] igt/gem_scheduler: Add gem_scheduler test John.C.Harrison
2016-04-21 9:43 ` ✓ Fi.CI.BAT: success for GPU scheduler for i915 driver (rev2) Patchwork
2016-04-22 15:37 ` [PATCH v6 00/34] GPU scheduler for i915 driver John Harrison
2016-04-23 9:57 ` ✗ Fi.CI.BAT: failure for GPU scheduler for i915 driver (rev2) Patchwork
2016-04-25 9:54 ` [PATCH v6 00/34] GPU scheduler for i915 driver Chris Wilson
2016-04-25 11:55 ` John Harrison
2016-04-26 13:20 ` Daniel Vetter
2016-05-05 11:54 ` John Harrison
2016-05-09 9:49 ` ✗ Fi.CI.BAT: warning for GPU scheduler for i915 driver (rev4) Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1462540771-22968-1-git-send-email-John.C.Harrison@Intel.com \
--to=john.c.harrison@intel.com \
--cc=Intel-GFX@Lists.FreeDesktop.Org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox