Skip to content

Commit f33a8a5

Browse files
committed
drm/i915: Merge wait_for_timelines with retire_request
wait_for_timelines is essentially the same loop as retiring requests (with an extra timeout), so merge the two into one routine. v2: i915_retire_requests_timeout and keep VT'd w/a as !interruptible Signed-off-by: Chris Wilson <[email protected]> Reviewed-by: Tvrtko Ursulin <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 33d8564 commit f33a8a5

File tree

14 files changed

+50
-96
lines changed

14 files changed

+50
-96
lines changed

drivers/gpu/drm/i915/gem/i915_gem_mman.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,7 @@ static int create_mmap_offset(struct drm_i915_gem_object *obj)
432432

433433
/* Attempt to reap some mmap space from dead objects */
434434
do {
435-
err = i915_gem_wait_for_idle(i915,
436-
I915_WAIT_INTERRUPTIBLE,
437-
MAX_SCHEDULE_TIMEOUT);
435+
err = i915_gem_wait_for_idle(i915, MAX_SCHEDULE_TIMEOUT);
438436
if (err)
439437
break;
440438

drivers/gpu/drm/i915/gem/i915_gem_pm.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ static bool switch_to_kernel_context_sync(struct intel_gt *gt)
5959
{
6060
bool result = !intel_gt_is_wedged(gt);
6161

62-
if (i915_gem_wait_for_idle(gt->i915,
63-
I915_WAIT_FOR_IDLE_BOOST,
64-
I915_GEM_IDLE_TIMEOUT) == -ETIME) {
62+
if (i915_gem_wait_for_idle(gt->i915, I915_GEM_IDLE_TIMEOUT) == -ETIME) {
6563
/* XXX hide warning from gem_eio */
6664
if (i915_modparams.reset) {
6765
dev_err(gt->i915->drm.dev,

drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ __sseu_finish(const char *name,
11371137

11381138
if ((flags & TEST_IDLE) && ret == 0) {
11391139
ret = i915_gem_wait_for_idle(ce->engine->i915,
1140-
0, MAX_SCHEDULE_TIMEOUT);
1140+
MAX_SCHEDULE_TIMEOUT);
11411141
if (ret)
11421142
return ret;
11431143

drivers/gpu/drm/i915/gt/intel_gt_pm.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ int intel_gt_resume(struct intel_gt *gt)
196196

197197
static void wait_for_idle(struct intel_gt *gt)
198198
{
199-
if (i915_gem_wait_for_idle(gt->i915, 0,
200-
I915_GEM_IDLE_TIMEOUT) == -ETIME) {
199+
if (i915_gem_wait_for_idle(gt->i915, I915_GEM_IDLE_TIMEOUT) == -ETIME) {
201200
/*
202201
* Forcibly cancel outstanding work and leave
203202
* the gpu quiet.

drivers/gpu/drm/i915/i915_debugfs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3635,9 +3635,7 @@ i915_drop_caches_set(void *data, u64 val)
36353635
i915_retire_requests(i915);
36363636

36373637
if (val & (DROP_IDLE | DROP_ACTIVE)) {
3638-
ret = i915_gem_wait_for_idle(i915,
3639-
I915_WAIT_INTERRUPTIBLE,
3640-
MAX_SCHEDULE_TIMEOUT);
3638+
ret = i915_gem_wait_for_idle(i915, MAX_SCHEDULE_TIMEOUT);
36413639
if (ret)
36423640
return ret;
36433641
}

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,8 +2321,7 @@ void i915_gem_driver_register(struct drm_i915_private *i915);
23212321
void i915_gem_driver_unregister(struct drm_i915_private *i915);
23222322
void i915_gem_driver_remove(struct drm_i915_private *dev_priv);
23232323
void i915_gem_driver_release(struct drm_i915_private *dev_priv);
2324-
int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
2325-
unsigned int flags, long timeout);
2324+
int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, long timeout);
23262325
void i915_gem_suspend(struct drm_i915_private *dev_priv);
23272326
void i915_gem_suspend_late(struct drm_i915_private *dev_priv);
23282327
void i915_gem_resume(struct drm_i915_private *dev_priv);

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -883,80 +883,21 @@ void i915_gem_runtime_suspend(struct drm_i915_private *i915)
883883
}
884884
}
885885

886-
static long
887-
wait_for_timelines(struct intel_gt *gt, unsigned int wait, long timeout)
888-
{
889-
struct intel_gt_timelines *timelines = &gt->timelines;
890-
struct intel_timeline *tl;
891-
unsigned long flags;
892-
893-
spin_lock_irqsave(&timelines->lock, flags);
894-
list_for_each_entry(tl, &timelines->active_list, link) {
895-
struct dma_fence *fence;
896-
897-
fence = i915_active_fence_get(&tl->last_request);
898-
if (!fence)
899-
continue;
900-
901-
spin_unlock_irqrestore(&timelines->lock, flags);
902-
903-
if (!dma_fence_is_i915(fence)) {
904-
timeout = dma_fence_wait_timeout(fence,
905-
flags & I915_WAIT_INTERRUPTIBLE,
906-
timeout);
907-
} else {
908-
struct i915_request *rq = to_request(fence);
909-
910-
/*
911-
* "Race-to-idle".
912-
*
913-
* Switching to the kernel context is often used as
914-
* a synchronous step prior to idling, e.g. in suspend
915-
* for flushing all current operations to memory before
916-
* sleeping. These we want to complete as quickly as
917-
* possible to avoid prolonged stalls, so allow the gpu
918-
* to boost to maximum clocks.
919-
*/
920-
if (flags & I915_WAIT_FOR_IDLE_BOOST)
921-
gen6_rps_boost(rq);
922-
923-
timeout = i915_request_wait(rq, flags, timeout);
924-
}
925-
926-
dma_fence_put(fence);
927-
if (timeout < 0)
928-
return timeout;
929-
930-
/* restart after reacquiring the lock */
931-
spin_lock_irqsave(&timelines->lock, flags);
932-
tl = list_entry(&timelines->active_list, typeof(*tl), link);
933-
}
934-
spin_unlock_irqrestore(&timelines->lock, flags);
935-
936-
return timeout;
937-
}
938-
939-
int i915_gem_wait_for_idle(struct drm_i915_private *i915,
940-
unsigned int flags, long timeout)
886+
int i915_gem_wait_for_idle(struct drm_i915_private *i915, long timeout)
941887
{
942888
struct intel_gt *gt = &i915->gt;
943889

944890
/* If the device is asleep, we have no requests outstanding */
945891
if (!intel_gt_pm_is_awake(gt))
946892
return 0;
947893

948-
do {
949-
timeout = wait_for_timelines(gt, flags, timeout);
950-
if (timeout < 0)
951-
return timeout;
952-
894+
while ((timeout = i915_retire_requests_timeout(i915, timeout)) > 0) {
953895
cond_resched();
954896
if (signal_pending(current))
955897
return -EINTR;
898+
}
956899

957-
} while (i915_retire_requests(i915));
958-
959-
return 0;
900+
return timeout;
960901
}
961902

962903
struct i915_vma *

drivers/gpu/drm/i915/i915_gem_evict.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ static int ggtt_flush(struct drm_i915_private *i915)
4646
* the hopes that we can then remove contexts and the like only
4747
* bound by their active reference.
4848
*/
49-
return i915_gem_wait_for_idle(i915,
50-
I915_WAIT_INTERRUPTIBLE,
51-
MAX_SCHEDULE_TIMEOUT);
49+
return i915_gem_wait_for_idle(i915, MAX_SCHEDULE_TIMEOUT);
5250
}
5351

5452
static bool
@@ -126,6 +124,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
126124
min_size, alignment, color,
127125
start, end, mode);
128126

127+
i915_retire_requests(vm->i915);
128+
129129
search_again:
130130
active = NULL;
131131
INIT_LIST_HEAD(&eviction_list);
@@ -264,13 +264,13 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
264264

265265
trace_i915_gem_evict_node(vm, target, flags);
266266

267-
/* Retire before we search the active list. Although we have
267+
/*
268+
* Retire before we search the active list. Although we have
268269
* reasonable accuracy in our retirement lists, we may have
269270
* a stray pin (preventing eviction) that can only be resolved by
270271
* retiring.
271272
*/
272-
if (!(flags & PIN_NONBLOCK))
273-
i915_retire_requests(vm->i915);
273+
i915_retire_requests(vm->i915);
274274

275275
if (i915_vm_has_cache_coloring(vm)) {
276276
/* Expand search to cover neighbouring guard pages (or lack!) */

drivers/gpu/drm/i915/i915_gem_gtt.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2528,7 +2528,9 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
25282528
struct i915_ggtt *ggtt = &dev_priv->ggtt;
25292529

25302530
if (unlikely(ggtt->do_idle_maps)) {
2531-
if (i915_gem_wait_for_idle(dev_priv, 0, MAX_SCHEDULE_TIMEOUT)) {
2531+
/* XXX This does not prevent more requests being submitted! */
2532+
if (i915_retire_requests_timeout(dev_priv,
2533+
-MAX_SCHEDULE_TIMEOUT)) {
25322534
DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");
25332535
/* Wait a bit, in hopes it avoids the hang */
25342536
udelay(10);

drivers/gpu/drm/i915/i915_request.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,13 +1508,19 @@ long i915_request_wait(struct i915_request *rq,
15081508
return timeout;
15091509
}
15101510

1511-
bool i915_retire_requests(struct drm_i915_private *i915)
1511+
long i915_retire_requests_timeout(struct drm_i915_private *i915, long timeout)
15121512
{
15131513
struct intel_gt_timelines *timelines = &i915->gt.timelines;
15141514
struct intel_timeline *tl, *tn;
1515+
unsigned long active_count = 0;
15151516
unsigned long flags;
1517+
bool interruptible;
15161518
LIST_HEAD(free);
15171519

1520+
interruptible = true;
1521+
if (timeout < 0)
1522+
timeout = -timeout, interruptible = false;
1523+
15181524
spin_lock_irqsave(&timelines->lock, flags);
15191525
list_for_each_entry_safe(tl, tn, &timelines->active_list, link) {
15201526
if (!mutex_trylock(&tl->mutex))
@@ -1525,13 +1531,27 @@ bool i915_retire_requests(struct drm_i915_private *i915)
15251531
tl->active_count++; /* pin the list element */
15261532
spin_unlock_irqrestore(&timelines->lock, flags);
15271533

1534+
if (timeout > 0) {
1535+
struct dma_fence *fence;
1536+
1537+
fence = i915_active_fence_get(&tl->last_request);
1538+
if (fence) {
1539+
timeout = dma_fence_wait_timeout(fence,
1540+
interruptible,
1541+
timeout);
1542+
dma_fence_put(fence);
1543+
}
1544+
}
1545+
15281546
retire_requests(tl);
15291547

15301548
spin_lock_irqsave(&timelines->lock, flags);
15311549

15321550
/* Resume iteration after dropping lock */
15331551
list_safe_reset_next(tl, tn, link);
1534-
if (!--tl->active_count)
1552+
if (--tl->active_count)
1553+
active_count += !!rcu_access_pointer(tl->last_request.fence);
1554+
else
15351555
list_del(&tl->link);
15361556

15371557
mutex_unlock(&tl->mutex);
@@ -1547,7 +1567,7 @@ bool i915_retire_requests(struct drm_i915_private *i915)
15471567
list_for_each_entry_safe(tl, tn, &free, link)
15481568
__intel_timeline_free(&tl->kref);
15491569

1550-
return !list_empty(&timelines->active_list);
1570+
return active_count ? timeout : 0;
15511571
}
15521572

15531573
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)

0 commit comments

Comments
 (0)