Commit ea746f36 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Expand bool interruptible to pass flags to i915_wait_request()

We need finer control over wakeup behaviour during i915_wait_request(),
so expand the current bool interruptible to a bitmask.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-9-chris@chris-wilson.co.uk
parent 2c7487a5
...@@ -4794,7 +4794,7 @@ i915_drop_caches_set(void *data, u64 val) ...@@ -4794,7 +4794,7 @@ i915_drop_caches_set(void *data, u64 val)
return ret; return ret;
if (val & DROP_ACTIVE) { if (val & DROP_ACTIVE) {
ret = i915_gem_wait_for_idle(dev_priv, true); ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE);
if (ret) if (ret)
goto unlock; goto unlock;
} }
......
...@@ -3270,7 +3270,7 @@ int __must_check i915_gem_init_hw(struct drm_device *dev); ...@@ -3270,7 +3270,7 @@ int __must_check i915_gem_init_hw(struct drm_device *dev);
void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev);
void i915_gem_cleanup_engines(struct drm_device *dev); void i915_gem_cleanup_engines(struct drm_device *dev);
int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
bool interruptible); unsigned int flags);
int __must_check i915_gem_suspend(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev);
void i915_gem_resume(struct drm_device *dev); void i915_gem_resume(struct drm_device *dev);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
......
...@@ -386,7 +386,8 @@ __unsafe_wait_rendering(struct drm_i915_gem_object *obj, ...@@ -386,7 +386,8 @@ __unsafe_wait_rendering(struct drm_i915_gem_object *obj,
int ret; int ret;
ret = i915_gem_active_wait_unlocked(&active[idx], ret = i915_gem_active_wait_unlocked(&active[idx],
true, NULL, rps); I915_WAIT_INTERRUPTIBLE,
NULL, rps);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -2026,7 +2027,7 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj) ...@@ -2026,7 +2027,7 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
* to claim that space for ourselves, we need to take the big * to claim that space for ourselves, we need to take the big
* struct_mutex to free the requests+objects and allocate our slot. * struct_mutex to free the requests+objects and allocate our slot.
*/ */
err = i915_gem_wait_for_idle(dev_priv, true); err = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE);
if (err) if (err)
return err; return err;
...@@ -2779,7 +2780,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ...@@ -2779,7 +2780,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
active = __I915_BO_ACTIVE(obj); active = __I915_BO_ACTIVE(obj);
for_each_active(active, idx) { for_each_active(active, idx) {
s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL; s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL;
ret = i915_gem_active_wait_unlocked(&obj->last_read[idx], true, ret = i915_gem_active_wait_unlocked(&obj->last_read[idx],
I915_WAIT_INTERRUPTIBLE,
timeout, rps); timeout, rps);
if (ret) if (ret)
break; break;
...@@ -2982,7 +2984,7 @@ int i915_vma_unbind(struct i915_vma *vma) ...@@ -2982,7 +2984,7 @@ int i915_vma_unbind(struct i915_vma *vma)
} }
int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
bool interruptible) unsigned int flags)
{ {
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
int ret; int ret;
...@@ -2991,7 +2993,7 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, ...@@ -2991,7 +2993,7 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
if (engine->last_context == NULL) if (engine->last_context == NULL)
continue; continue;
ret = intel_engine_idle(engine, interruptible); ret = intel_engine_idle(engine, flags);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -3746,7 +3748,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) ...@@ -3746,7 +3748,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
if (target == NULL) if (target == NULL)
return 0; return 0;
ret = i915_wait_request(target, true, NULL, NULL); ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, NULL, NULL);
i915_gem_request_put(target); i915_gem_request_put(target);
return ret; return ret;
...@@ -4302,7 +4304,7 @@ int i915_gem_suspend(struct drm_device *dev) ...@@ -4302,7 +4304,7 @@ int i915_gem_suspend(struct drm_device *dev)
if (ret) if (ret)
goto err; goto err;
ret = i915_gem_wait_for_idle(dev_priv, true); ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE);
if (ret) if (ret)
goto err; goto err;
......
...@@ -170,7 +170,7 @@ i915_gem_evict_something(struct i915_address_space *vm, ...@@ -170,7 +170,7 @@ i915_gem_evict_something(struct i915_address_space *vm,
if (ret) if (ret)
return ret; return ret;
ret = i915_gem_wait_for_idle(dev_priv, true); ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE);
if (ret) if (ret)
return ret; return ret;
...@@ -275,7 +275,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) ...@@ -275,7 +275,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
return ret; return ret;
} }
ret = i915_gem_wait_for_idle(dev_priv, true); ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE);
if (ret) if (ret)
return ret; return ret;
......
...@@ -2683,7 +2683,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) ...@@ -2683,7 +2683,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt *ggtt = &dev_priv->ggtt;
if (unlikely(ggtt->do_idle_maps)) { if (unlikely(ggtt->do_idle_maps)) {
if (i915_gem_wait_for_idle(dev_priv, false)) { if (i915_gem_wait_for_idle(dev_priv, 0)) {
DRM_ERROR("Failed to wait for idle; VT'd may hang.\n"); DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");
/* Wait a bit, in hopes it avoids the hang */ /* Wait a bit, in hopes it avoids the hang */
udelay(10); udelay(10);
......
...@@ -260,7 +260,7 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) ...@@ -260,7 +260,7 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno)
/* Carefully retire all requests without writing to the rings */ /* Carefully retire all requests without writing to the rings */
for_each_engine(engine, dev_priv) { for_each_engine(engine, dev_priv) {
ret = intel_engine_idle(engine, true); ret = intel_engine_idle(engine, I915_WAIT_INTERRUPTIBLE);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -598,7 +598,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, ...@@ -598,7 +598,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req,
/** /**
* i915_wait_request - wait until execution of request has finished * i915_wait_request - wait until execution of request has finished
* @req: duh! * @req: duh!
* @interruptible: do an interruptible wait (normally yes) * @flags: how to wait
* @timeout: in - how long to wait (NULL forever); out - how much time remaining * @timeout: in - how long to wait (NULL forever); out - how much time remaining
* @rps: client to charge for RPS boosting * @rps: client to charge for RPS boosting
* *
...@@ -613,11 +613,12 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, ...@@ -613,11 +613,12 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req,
* errno with remaining time filled in timeout argument. * errno with remaining time filled in timeout argument.
*/ */
int i915_wait_request(struct drm_i915_gem_request *req, int i915_wait_request(struct drm_i915_gem_request *req,
bool interruptible, unsigned int flags,
s64 *timeout, s64 *timeout,
struct intel_rps_client *rps) struct intel_rps_client *rps)
{ {
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; const int state = flags & I915_WAIT_INTERRUPTIBLE ?
TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
DEFINE_WAIT(reset); DEFINE_WAIT(reset);
struct intel_wait wait; struct intel_wait wait;
unsigned long timeout_remain; unsigned long timeout_remain;
......
...@@ -218,10 +218,11 @@ struct intel_rps_client; ...@@ -218,10 +218,11 @@ struct intel_rps_client;
#define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p)) #define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p))
int i915_wait_request(struct drm_i915_gem_request *req, int i915_wait_request(struct drm_i915_gem_request *req,
bool interruptible, unsigned int flags,
s64 *timeout, s64 *timeout,
struct intel_rps_client *rps) struct intel_rps_client *rps)
__attribute__((nonnull(1))); __attribute__((nonnull(1)));
#define I915_WAIT_INTERRUPTIBLE BIT(0)
static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine); static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine);
...@@ -575,13 +576,13 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) ...@@ -575,13 +576,13 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex)
if (!request) if (!request)
return 0; return 0;
return i915_wait_request(request, true, NULL, NULL); return i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL);
} }
/** /**
* i915_gem_active_wait_unlocked - waits until the request is completed * i915_gem_active_wait_unlocked - waits until the request is completed
* @active - the active request on which to wait * @active - the active request on which to wait
* @interruptible - whether the wait can be woken by a userspace signal * @flags - how to wait
* @timeout - how long to wait at most * @timeout - how long to wait at most
* @rps - userspace client to charge for a waitboost * @rps - userspace client to charge for a waitboost
* *
...@@ -602,7 +603,7 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) ...@@ -602,7 +603,7 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex)
*/ */
static inline int static inline int
i915_gem_active_wait_unlocked(const struct i915_gem_active *active, i915_gem_active_wait_unlocked(const struct i915_gem_active *active,
bool interruptible, unsigned int flags,
s64 *timeout, s64 *timeout,
struct intel_rps_client *rps) struct intel_rps_client *rps)
{ {
...@@ -611,7 +612,7 @@ i915_gem_active_wait_unlocked(const struct i915_gem_active *active, ...@@ -611,7 +612,7 @@ i915_gem_active_wait_unlocked(const struct i915_gem_active *active,
request = i915_gem_active_get_unlocked(active); request = i915_gem_active_get_unlocked(active);
if (request) { if (request) {
ret = i915_wait_request(request, interruptible, timeout, rps); ret = i915_wait_request(request, flags, timeout, rps);
i915_gem_request_put(request); i915_gem_request_put(request);
} }
...@@ -638,7 +639,7 @@ i915_gem_active_retire(struct i915_gem_active *active, ...@@ -638,7 +639,7 @@ i915_gem_active_retire(struct i915_gem_active *active,
if (!request) if (!request)
return 0; return 0;
ret = i915_wait_request(request, true, NULL, NULL); ret = i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL);
if (ret) if (ret)
return ret; return ret;
......
...@@ -323,7 +323,7 @@ i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv, ...@@ -323,7 +323,7 @@ i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv,
unsigned long timeout = jiffies + msecs_to_jiffies_timeout(timeout_ms); unsigned long timeout = jiffies + msecs_to_jiffies_timeout(timeout_ms);
do { do {
if (i915_gem_wait_for_idle(dev_priv, false) == 0 && if (i915_gem_wait_for_idle(dev_priv, 0) == 0 &&
i915_gem_shrinker_lock(&dev_priv->drm, &slu->unlock)) i915_gem_shrinker_lock(&dev_priv->drm, &slu->unlock))
break; break;
...@@ -414,7 +414,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr ...@@ -414,7 +414,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
return NOTIFY_DONE; return NOTIFY_DONE;
/* Force everything onto the inactive lists */ /* Force everything onto the inactive lists */
ret = i915_gem_wait_for_idle(dev_priv, false); ret = i915_gem_wait_for_idle(dev_priv, 0);
if (ret) if (ret)
goto out; goto out;
......
...@@ -68,7 +68,7 @@ static void wait_rendering(struct drm_i915_gem_object *obj) ...@@ -68,7 +68,7 @@ static void wait_rendering(struct drm_i915_gem_object *obj)
for_each_active(active, idx) for_each_active(active, idx)
i915_gem_active_wait_unlocked(&obj->last_read[idx], i915_gem_active_wait_unlocked(&obj->last_read[idx],
false, NULL, NULL); 0, NULL, NULL);
} }
static void cancel_userptr(struct work_struct *work) static void cancel_userptr(struct work_struct *work)
......
...@@ -12022,8 +12022,7 @@ static void intel_mmio_flip_work_func(struct work_struct *w) ...@@ -12022,8 +12022,7 @@ static void intel_mmio_flip_work_func(struct work_struct *w)
if (work->flip_queued_req) if (work->flip_queued_req)
WARN_ON(i915_wait_request(work->flip_queued_req, WARN_ON(i915_wait_request(work->flip_queued_req,
false, NULL, 0, NULL, NO_WAITBOOST));
NO_WAITBOOST));
/* For framebuffer backed by dmabuf, wait for fence */ /* For framebuffer backed by dmabuf, wait for fence */
resv = i915_gem_object_get_dmabuf_resv(obj); resv = i915_gem_object_get_dmabuf_resv(obj);
...@@ -14071,7 +14070,8 @@ static int intel_atomic_prepare_commit(struct drm_device *dev, ...@@ -14071,7 +14070,8 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
continue; continue;
ret = i915_wait_request(intel_plane_state->wait_req, ret = i915_wait_request(intel_plane_state->wait_req,
true, NULL, NULL); I915_WAIT_INTERRUPTIBLE,
NULL, NULL);
if (ret) { if (ret) {
/* Any hang should be swallowed by the wait */ /* Any hang should be swallowed by the wait */
WARN_ON(ret == -EIO); WARN_ON(ret == -EIO);
...@@ -14289,7 +14289,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -14289,7 +14289,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
continue; continue;
ret = i915_wait_request(intel_plane_state->wait_req, ret = i915_wait_request(intel_plane_state->wait_req,
true, NULL, NULL); 0, NULL, NULL);
/* EIO should be eaten, and we can't get interrupted in the /* EIO should be eaten, and we can't get interrupted in the
* worker, and blocking commits have waited already. */ * worker, and blocking commits have waited already. */
WARN_ON(ret); WARN_ON(ret);
......
...@@ -2223,7 +2223,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) ...@@ -2223,7 +2223,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
if (WARN_ON(&target->ring_link == &ring->request_list)) if (WARN_ON(&target->ring_link == &ring->request_list))
return -ENOSPC; return -ENOSPC;
ret = i915_wait_request(target, true, NULL, NO_WAITBOOST); ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE,
NULL, NO_WAITBOOST);
if (ret) if (ret)
return ret; return ret;
......
...@@ -489,11 +489,11 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size); ...@@ -489,11 +489,11 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size);
void intel_engine_cleanup_common(struct intel_engine_cs *engine); void intel_engine_cleanup_common(struct intel_engine_cs *engine);
static inline int intel_engine_idle(struct intel_engine_cs *engine, static inline int intel_engine_idle(struct intel_engine_cs *engine,
bool interruptible) unsigned int flags)
{ {
/* Wait upon the last request to be completed */ /* Wait upon the last request to be completed */
return i915_gem_active_wait_unlocked(&engine->last_request, return i915_gem_active_wait_unlocked(&engine->last_request,
interruptible, NULL, NULL); flags, NULL, NULL);
} }
int intel_init_render_ring_buffer(struct intel_engine_cs *engine); int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment