While the fairness scheduler also currently uses batches to attempt to keep things fair, that is an implementation detail. A fairness scheduler should still be fair even if we achieve a better granularity on future products. The batch scheduler on the other hand is meant to remain relevant even in light of newer scheduling metrics. The batch scheduler introduces a per-client high and low watermark. These watermarks define when the client will get blocked, and when it will get unblocked in terms of number of batches submitted. For example, if we wanted to run X as unthrottled, we could use a high watermark of -1, and a low watermark of 0. In theory it is also accomplished by high watermark = low watermark. Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- drivers/gpu/drm/i915/i915_dma.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 5 +++- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 32 +++++++++++++++++++++------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index df06a7e..a871b95 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2211,6 +2211,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) INIT_LIST_HEAD(&file_priv->client_link); file_priv->outstanding_requests = 0; file_priv->forced_throttles = 0; + file_priv->high_watermark = 50; + file_priv->low_watermark = 5; mutex_lock(&dev->struct_mutex); dev_priv->num_clients++; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a12445b..9933e01 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -746,7 +746,8 @@ typedef struct drm_i915_private { struct { #define I915_SCHEDULER_NONE 0 #define I915_SCHEDULER_FAIR 1 - #define I915_SCHEDULER_INVALID 2 + #define I915_SCHEDULER_BATCH 2 + #define I915_SCHEDULER_INVALID 3 unsigned type; /* Point at which we consider blocking */ unsigned high_watermark; @@ -942,6 +943,8 @@ struct drm_i915_file_private { struct list_head request_list; int outstanding_requests; int forced_throttles; + unsigned high_watermark; + unsigned low_watermark; struct list_head client_link; }; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c2e96be..a24e890 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -968,17 +968,35 @@ i915_schedule(struct drm_device *dev, struct intel_ring_buffer *ring, struct drm struct drm_i915_gem_request *request = NULL; u32 seqno = 0; int ret, i = 0; + uint32_t high_watermark = 0, low_watermark = 0; -#define BLOCK_CONDITION ( \ - (dev_priv->scheduler.type != I915_SCHEDULER_NONE) && \ - (file_priv->outstanding_requests > dev_priv->scheduler.high_watermark)) + switch (dev_priv->scheduler.type) { + case I915_SCHEDULER_NONE: + return I915_DONE; + case I915_SCHEDULER_FAIR: + high_watermark = dev_priv->scheduler.high_watermark; + low_watermark = dev_priv->scheduler.low_watermark; + break; + case I915_SCHEDULER_BATCH: + /* Can't do anything until we hold the spinlock */ + break; + default: + WARN_ON(1); + return I915_DONE; + } + +#define BLOCK_CONDITION (file_priv->outstanding_requests > high_watermark) #define OUT_CONDITION ( \ (atomic_read(&dev_priv->mm.wedged)) || \ (dev_priv->mm.suspended)) -#define RUNNABLE ( \ - file_priv->outstanding_requests < dev_priv->scheduler.low_watermark) +#define RUNNABLE (file_priv->outstanding_requests < low_watermark) spin_lock(&file_priv->lock); + if (dev_priv->scheduler.type == I915_SCHEDULER_BATCH) { + BUG_ON(high_watermark != 0 || low_watermark != 0); + high_watermark = file_priv->high_watermark; + low_watermark = file_priv->low_watermark; + } if (!BLOCK_CONDITION) { spin_unlock(&file_priv->lock); return I915_DONE; @@ -997,7 +1015,7 @@ i915_schedule(struct drm_device *dev, struct intel_ring_buffer *ring, struct drm } list_for_each_entry(request, &file_priv->request_list, client_list) { - if (i == dev_priv->scheduler.low_watermark) { + if (i == low_watermark) { seqno = request->seqno; break; } @@ -1005,7 +1023,7 @@ i915_schedule(struct drm_device *dev, struct intel_ring_buffer *ring, struct drm } spin_unlock(&file_priv->lock); - BUG_ON(seqno == 0 || i < dev_priv->scheduler.low_watermark); + BUG_ON(seqno == 0 || i < low_watermark); ret = i915_wait_request(ring, seqno, true); BUG_ON(!mutex_is_locked(&dev->struct_mutex)); -- 1.7.7.3