Skip to content

Commit 1f15b76

Browse files
committed
drm/i915: Separate GPU hang waitqueue from advance
Currently __i915_wait_request uses a per-engine wait_queue_t for the dual purpose of waking after the GPU advances or for waking after an error. In the future, we may add even more wake sources and require greater separation, but for now we can conceptually simplify wakeups by separating the two sources. In particular, this allows us to use different wait-queues (e.g. one on the engine advancement, a global one for errors and one on each requests) without any hassle. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1467390209-3576-5-git-send-email-chris@chris-wilson.co.uk
1 parent 26a02b8 commit 1f15b76

File tree

3 files changed

+15
-15
lines changed

3 files changed

+15
-15
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,12 @@ struct i915_gpu_error {
14091409
#define I915_RESET_IN_PROGRESS_FLAG 1
14101410
#define I915_WEDGED (1 << 31)
14111411

1412+
/**
1413+
* Waitqueue to signal when a hang is detected. Used to for waiters
1414+
* to release the struct_mutex for the reset to procede.
1415+
*/
1416+
wait_queue_head_t wait_queue;
1417+
14121418
/**
14131419
* Waitqueue to signal when the reset has completed. Used by clients
14141420
* that wait for dev_priv->mm.wedged to settle.

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
14551455
const bool irq_test_in_progress =
14561456
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_engine_flag(engine);
14571457
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
1458+
DEFINE_WAIT(reset);
14581459
DEFINE_WAIT(wait);
14591460
unsigned long timeout_expire;
14601461
s64 before = 0; /* Only to silence a compiler warning. */
@@ -1499,6 +1500,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
14991500
goto out;
15001501
}
15011502

1503+
add_wait_queue(&dev_priv->gpu_error.wait_queue, &reset);
15021504
for (;;) {
15031505
struct timer_list timer;
15041506

@@ -1557,6 +1559,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
15571559
destroy_timer_on_stack(&timer);
15581560
}
15591561
}
1562+
remove_wait_queue(&dev_priv->gpu_error.wait_queue, &reset);
1563+
15601564
if (!irq_test_in_progress)
15611565
engine->irq_put(engine);
15621566

@@ -5287,6 +5291,7 @@ i915_gem_load_init(struct drm_device *dev)
52875291
i915_gem_retire_work_handler);
52885292
INIT_DELAYED_WORK(&dev_priv->mm.idle_work,
52895293
i915_gem_idle_work_handler);
5294+
init_waitqueue_head(&dev_priv->gpu_error.wait_queue);
52905295
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
52915296

52925297
dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,11 +2488,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
24882488
return ret;
24892489
}
24902490

2491-
static void i915_error_wake_up(struct drm_i915_private *dev_priv,
2492-
bool reset_completed)
2491+
static void i915_error_wake_up(struct drm_i915_private *dev_priv)
24932492
{
2494-
struct intel_engine_cs *engine;
2495-
24962493
/*
24972494
* Notify all waiters for GPU completion events that reset state has
24982495
* been changed, and that they need to restart their wait after
@@ -2501,18 +2498,10 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv,
25012498
*/
25022499

25032500
/* Wake up __wait_seqno, potentially holding dev->struct_mutex. */
2504-
for_each_engine(engine, dev_priv)
2505-
wake_up_all(&engine->irq_queue);
2501+
wake_up_all(&dev_priv->gpu_error.wait_queue);
25062502

25072503
/* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */
25082504
wake_up_all(&dev_priv->pending_flip_queue);
2509-
2510-
/*
2511-
* Signal tasks blocked in i915_gem_wait_for_error that the pending
2512-
* reset state is cleared.
2513-
*/
2514-
if (reset_completed)
2515-
wake_up_all(&dev_priv->gpu_error.reset_queue);
25162505
}
25172506

25182507
/**
@@ -2577,7 +2566,7 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
25772566
* Note: The wake_up also serves as a memory barrier so that
25782567
* waiters see the update value of the reset counter atomic_t.
25792568
*/
2580-
i915_error_wake_up(dev_priv, true);
2569+
wake_up_all(&dev_priv->gpu_error.reset_queue);
25812570
}
25822571
}
25832572

@@ -2714,7 +2703,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
27142703
* ensure that the waiters see the updated value of the reset
27152704
* counter atomic_t.
27162705
*/
2717-
i915_error_wake_up(dev_priv, false);
2706+
i915_error_wake_up(dev_priv);
27182707
}
27192708

27202709
i915_reset_and_wakeup(dev_priv);

0 commit comments

Comments
 (0)