@@ -198,6 +198,12 @@ i915_priotree_init(struct i915_priotree *pt)
198
198
pt -> priority = INT_MIN ;
199
199
}
200
200
201
+ static void unreserve_seqno (struct intel_engine_cs * engine )
202
+ {
203
+ GEM_BUG_ON (!engine -> timeline -> inflight_seqnos );
204
+ engine -> timeline -> inflight_seqnos -- ;
205
+ }
206
+
201
207
void i915_gem_retire_noop (struct i915_gem_active * active ,
202
208
struct drm_i915_gem_request * request )
203
209
{
@@ -237,6 +243,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
237
243
& request -> i915 -> gt .idle_work ,
238
244
msecs_to_jiffies (100 ));
239
245
}
246
+ unreserve_seqno (request -> engine );
240
247
241
248
/* Walk through the active list, calling retire on each. This allows
242
249
* objects to track their GPU activity and mark themselves as idle
@@ -307,7 +314,7 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req)
307
314
} while (tmp != req );
308
315
}
309
316
310
- static int i915_gem_init_global_seqno (struct drm_i915_private * i915 , u32 seqno )
317
+ static int reset_all_global_seqno (struct drm_i915_private * i915 , u32 seqno )
311
318
{
312
319
struct i915_gem_timeline * timeline = & i915 -> gt .global_timeline ;
313
320
struct intel_engine_cs * engine ;
@@ -325,15 +332,19 @@ static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno)
325
332
GEM_BUG_ON (i915 -> gt .active_requests > 1 );
326
333
327
334
/* If the seqno wraps around, we need to clear the breadcrumb rbtree */
328
- if (!i915_seqno_passed (seqno , atomic_read (& timeline -> seqno ))) {
329
- while (intel_breadcrumbs_busy (i915 ))
330
- cond_resched (); /* spin until threads are complete */
331
- }
332
- atomic_set (& timeline -> seqno , seqno );
335
+ for_each_engine (engine , i915 , id ) {
336
+ struct intel_timeline * tl = & timeline -> engine [id ];
333
337
334
- /* Finally reset hw state */
335
- for_each_engine (engine , i915 , id )
338
+ if (!i915_seqno_passed (seqno , tl -> seqno )) {
339
+ /* spin until threads are complete */
340
+ while (intel_breadcrumbs_busy (engine ))
341
+ cond_resched ();
342
+ }
343
+
344
+ /* Finally reset hw state */
345
+ tl -> seqno = seqno ;
336
346
intel_engine_init_global_seqno (engine , seqno );
347
+ }
337
348
338
349
list_for_each_entry (timeline , & i915 -> gt .timelines , link ) {
339
350
for_each_engine (engine , i915 , id ) {
@@ -358,37 +369,38 @@ int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno)
358
369
/* HWS page needs to be set less than what we
359
370
* will inject to ring
360
371
*/
361
- return i915_gem_init_global_seqno (dev_priv , seqno - 1 );
372
+ return reset_all_global_seqno (dev_priv , seqno - 1 );
362
373
}
363
374
364
- static int reserve_global_seqno (struct drm_i915_private * i915 )
375
+ static int reserve_seqno (struct intel_engine_cs * engine )
365
376
{
366
- u32 active_requests = ++ i915 -> gt . active_requests ;
367
- u32 seqno = atomic_read ( & i915 -> gt . global_timeline . seqno ) ;
377
+ u32 active = ++ engine -> timeline -> inflight_seqnos ;
378
+ u32 seqno = engine -> timeline -> seqno ;
368
379
int ret ;
369
380
370
381
/* Reservation is fine until we need to wrap around */
371
- if (likely (seqno + active_requests > seqno ))
382
+ if (likely (! add_overflows ( seqno , active ) ))
372
383
return 0 ;
373
384
374
- ret = i915_gem_init_global_seqno (i915 , 0 );
385
+ /* Even though we are tracking inflight seqno individually on each
386
+ * engine, other engines may be observing us using hw semaphores and
387
+ * so we need to idle all engines before wrapping around this engine.
388
+ * As all engines are then idle, we can reset the seqno on all, so
389
+ * we don't stall in quick succession if each engine is being
390
+ * similarly utilized.
391
+ */
392
+ ret = reset_all_global_seqno (engine -> i915 , 0 );
375
393
if (ret ) {
376
- i915 -> gt . active_requests -- ;
394
+ engine -> timeline -> inflight_seqnos -- ;
377
395
return ret ;
378
396
}
379
397
380
398
return 0 ;
381
399
}
382
400
383
- static u32 __timeline_get_seqno (struct i915_gem_timeline * tl )
384
- {
385
- /* seqno only incremented under a mutex */
386
- return ++ tl -> seqno .counter ;
387
- }
388
-
389
- static u32 timeline_get_seqno (struct i915_gem_timeline * tl )
401
+ static u32 timeline_get_seqno (struct intel_timeline * tl )
390
402
{
391
- return atomic_inc_return ( & tl -> seqno ) ;
403
+ return ++ tl -> seqno ;
392
404
}
393
405
394
406
void __i915_gem_request_submit (struct drm_i915_gem_request * request )
@@ -402,14 +414,10 @@ void __i915_gem_request_submit(struct drm_i915_gem_request *request)
402
414
GEM_BUG_ON (timeline == request -> timeline );
403
415
assert_spin_locked (& timeline -> lock );
404
416
405
- seqno = timeline_get_seqno (timeline -> common );
417
+ seqno = timeline_get_seqno (timeline );
406
418
GEM_BUG_ON (!seqno );
407
419
GEM_BUG_ON (i915_seqno_passed (intel_engine_get_seqno (engine ), seqno ));
408
420
409
- GEM_BUG_ON (i915_seqno_passed (timeline -> last_submitted_seqno , seqno ));
410
- request -> previous_seqno = timeline -> last_submitted_seqno ;
411
- timeline -> last_submitted_seqno = seqno ;
412
-
413
421
/* We may be recursing from the signal callback of another i915 fence */
414
422
spin_lock_nested (& request -> lock , SINGLE_DEPTH_NESTING );
415
423
request -> global_seqno = seqno ;
@@ -516,7 +524,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
516
524
if (ret )
517
525
return ERR_PTR (ret );
518
526
519
- ret = reserve_global_seqno ( dev_priv );
527
+ ret = reserve_seqno ( engine );
520
528
if (ret )
521
529
goto err_unpin ;
522
530
@@ -568,7 +576,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
568
576
& i915_fence_ops ,
569
577
& req -> lock ,
570
578
req -> timeline -> fence_context ,
571
- __timeline_get_seqno (req -> timeline -> common ));
579
+ timeline_get_seqno (req -> timeline ));
572
580
573
581
/* We bump the ref for the fence chain */
574
582
i915_sw_fence_init (& i915_gem_request_get (req )-> submit , submit_notify );
@@ -613,6 +621,8 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
613
621
*/
614
622
req -> head = req -> ring -> tail ;
615
623
624
+ /* Check that we didn't interrupt ourselves with a new request */
625
+ GEM_BUG_ON (req -> timeline -> seqno != req -> fence .seqno );
616
626
return req ;
617
627
618
628
err_ctx :
@@ -623,7 +633,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
623
633
624
634
kmem_cache_free (dev_priv -> requests , req );
625
635
err_unreserve :
626
- dev_priv -> gt . active_requests -- ;
636
+ unreserve_seqno ( engine ) ;
627
637
err_unpin :
628
638
engine -> context_unpin (engine , ctx );
629
639
return ERR_PTR (ret );
@@ -836,8 +846,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
836
846
* our i915_gem_request_alloc() and called __i915_add_request() before
837
847
* us, the timeline will hold its seqno which is later than ours.
838
848
*/
839
- GEM_BUG_ON (i915_seqno_passed (timeline -> last_submitted_seqno ,
840
- request -> fence .seqno ));
849
+ GEM_BUG_ON (timeline -> seqno != request -> fence .seqno );
841
850
842
851
/*
843
852
* To ensure that this call will not fail, space for its emissions
@@ -891,16 +900,14 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
891
900
list_add_tail (& request -> link , & timeline -> requests );
892
901
spin_unlock_irq (& timeline -> lock );
893
902
894
- GEM_BUG_ON (i915_seqno_passed (timeline -> last_submitted_seqno ,
895
- request -> fence .seqno ));
896
-
897
- timeline -> last_submitted_seqno = request -> fence .seqno ;
903
+ GEM_BUG_ON (timeline -> seqno != request -> fence .seqno );
898
904
i915_gem_active_set (& timeline -> last_request , request );
899
905
900
906
list_add_tail (& request -> ring_link , & ring -> request_list );
901
907
request -> emitted_jiffies = jiffies ;
902
908
903
- i915_gem_mark_busy (engine );
909
+ if (!request -> i915 -> gt .active_requests ++ )
910
+ i915_gem_mark_busy (engine );
904
911
905
912
/* Let the backend know a new request has arrived that may need
906
913
* to adjust the existing execution schedule due to a high priority
0 commit comments