@@ -270,7 +270,8 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
270
270
if (!e )
271
271
return ERR_PTR (- ENOMEM );
272
272
273
- init_rcu_head (& e -> rcu );
273
+ e -> ctx = ctx ;
274
+
274
275
for_each_engine (engine , gt , id ) {
275
276
struct intel_context * ce ;
276
277
@@ -450,7 +451,7 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce)
450
451
return engine ;
451
452
}
452
453
453
- static void kill_context (struct i915_gem_context * ctx )
454
+ static void kill_engines (struct i915_gem_engines * engines )
454
455
{
455
456
struct i915_gem_engines_iter it ;
456
457
struct intel_context * ce ;
@@ -462,7 +463,7 @@ static void kill_context(struct i915_gem_context *ctx)
462
463
* However, we only care about pending requests, so only include
463
464
* engines on which there are incomplete requests.
464
465
*/
465
- for_each_gem_engine (ce , __context_engines_static ( ctx ) , it ) {
466
+ for_each_gem_engine (ce , engines , it ) {
466
467
struct intel_engine_cs * engine ;
467
468
468
469
if (intel_context_set_banned (ce ))
@@ -484,8 +485,37 @@ static void kill_context(struct i915_gem_context *ctx)
484
485
* the context from the GPU, we have to resort to a full
485
486
* reset. We hope the collateral damage is worth it.
486
487
*/
487
- __reset_context (ctx , engine );
488
+ __reset_context (engines -> ctx , engine );
489
+ }
490
+ }
491
+
492
+ static void kill_stale_engines (struct i915_gem_context * ctx )
493
+ {
494
+ struct i915_gem_engines * pos , * next ;
495
+ unsigned long flags ;
496
+
497
+ spin_lock_irqsave (& ctx -> stale .lock , flags );
498
+ list_for_each_entry_safe (pos , next , & ctx -> stale .engines , link ) {
499
+ if (!i915_sw_fence_await (& pos -> fence ))
500
+ continue ;
501
+
502
+ spin_unlock_irqrestore (& ctx -> stale .lock , flags );
503
+
504
+ kill_engines (pos );
505
+
506
+ spin_lock_irqsave (& ctx -> stale .lock , flags );
507
+ list_safe_reset_next (pos , next , link );
508
+ list_del_init (& pos -> link ); /* decouple from FENCE_COMPLETE */
509
+
510
+ i915_sw_fence_complete (& pos -> fence );
488
511
}
512
+ spin_unlock_irqrestore (& ctx -> stale .lock , flags );
513
+ }
514
+
515
+ static void kill_context (struct i915_gem_context * ctx )
516
+ {
517
+ kill_stale_engines (ctx );
518
+ kill_engines (__context_engines_static (ctx ));
489
519
}
490
520
491
521
static void set_closed_name (struct i915_gem_context * ctx )
@@ -602,6 +632,9 @@ __create_context(struct drm_i915_private *i915)
602
632
ctx -> sched .priority = I915_USER_PRIORITY (I915_PRIORITY_NORMAL );
603
633
mutex_init (& ctx -> mutex );
604
634
635
+ spin_lock_init (& ctx -> stale .lock );
636
+ INIT_LIST_HEAD (& ctx -> stale .engines );
637
+
605
638
mutex_init (& ctx -> engines_mutex );
606
639
e = default_engines (ctx );
607
640
if (IS_ERR (e )) {
@@ -1529,6 +1562,77 @@ static const i915_user_extension_fn set_engines__extensions[] = {
1529
1562
[I915_CONTEXT_ENGINES_EXT_BOND ] = set_engines__bond ,
1530
1563
};
1531
1564
1565
+ static int engines_notify (struct i915_sw_fence * fence ,
1566
+ enum i915_sw_fence_notify state )
1567
+ {
1568
+ struct i915_gem_engines * engines =
1569
+ container_of (fence , typeof (* engines ), fence );
1570
+
1571
+ switch (state ) {
1572
+ case FENCE_COMPLETE :
1573
+ if (!list_empty (& engines -> link )) {
1574
+ struct i915_gem_context * ctx = engines -> ctx ;
1575
+ unsigned long flags ;
1576
+
1577
+ spin_lock_irqsave (& ctx -> stale .lock , flags );
1578
+ list_del (& engines -> link );
1579
+ spin_unlock_irqrestore (& ctx -> stale .lock , flags );
1580
+ }
1581
+ break ;
1582
+
1583
+ case FENCE_FREE :
1584
+ init_rcu_head (& engines -> rcu );
1585
+ call_rcu (& engines -> rcu , free_engines_rcu );
1586
+ break ;
1587
+ }
1588
+
1589
+ return NOTIFY_DONE ;
1590
+ }
1591
+
1592
+ static void engines_idle_release (struct i915_gem_engines * engines )
1593
+ {
1594
+ struct i915_gem_engines_iter it ;
1595
+ struct intel_context * ce ;
1596
+ unsigned long flags ;
1597
+
1598
+ GEM_BUG_ON (!engines );
1599
+ i915_sw_fence_init (& engines -> fence , engines_notify );
1600
+
1601
+ INIT_LIST_HEAD (& engines -> link );
1602
+ spin_lock_irqsave (& engines -> ctx -> stale .lock , flags );
1603
+ if (!i915_gem_context_is_closed (engines -> ctx ))
1604
+ list_add (& engines -> link , & engines -> ctx -> stale .engines );
1605
+ spin_unlock_irqrestore (& engines -> ctx -> stale .lock , flags );
1606
+ if (list_empty (& engines -> link )) /* raced, already closed */
1607
+ goto kill ;
1608
+
1609
+ for_each_gem_engine (ce , engines , it ) {
1610
+ struct dma_fence * fence ;
1611
+ int err ;
1612
+
1613
+ if (!ce -> timeline )
1614
+ continue ;
1615
+
1616
+ fence = i915_active_fence_get (& ce -> timeline -> last_request );
1617
+ if (!fence )
1618
+ continue ;
1619
+
1620
+ err = i915_sw_fence_await_dma_fence (& engines -> fence ,
1621
+ fence , 0 ,
1622
+ GFP_KERNEL );
1623
+
1624
+ dma_fence_put (fence );
1625
+ if (err < 0 )
1626
+ goto kill ;
1627
+ }
1628
+ goto out ;
1629
+
1630
+ kill :
1631
+ kill_engines (engines );
1632
+ out :
1633
+ i915_sw_fence_commit (& engines -> fence );
1634
+ }
1635
+
1532
1636
static int
1533
1637
set_engines (struct i915_gem_context * ctx ,
1534
1638
const struct drm_i915_gem_context_param * args )
@@ -1571,7 +1675,8 @@ set_engines(struct i915_gem_context *ctx,
1571
1675
if (!set .engines )
1572
1676
return - ENOMEM ;
1573
1677
1574
- init_rcu_head (& set .engines -> rcu );
1678
+ set .engines -> ctx = ctx ;
1679
+
1575
1680
for (n = 0 ; n < num_engines ; n ++ ) {
1576
1681
struct i915_engine_class_instance ci ;
1577
1682
struct intel_engine_cs * engine ;
@@ -1631,7 +1736,8 @@ set_engines(struct i915_gem_context *ctx,
1631
1736
set .engines = rcu_replace_pointer (ctx -> engines , set .engines , 1 );
1632
1737
mutex_unlock (& ctx -> engines_mutex );
1633
1738
1634
- call_rcu (& set .engines -> rcu , free_engines_rcu );
1739
+ /* Keep track of old engine sets for kill_context() */
1740
+ engines_idle_release (set .engines );
1635
1741
1636
1742
return 0 ;
1637
1743
}
@@ -1646,7 +1752,6 @@ __copy_engines(struct i915_gem_engines *e)
1646
1752
if (!copy )
1647
1753
return ERR_PTR (- ENOMEM );
1648
1754
1649
- init_rcu_head (& copy -> rcu );
1650
1755
for (n = 0 ; n < e -> num_engines ; n ++ ) {
1651
1756
if (e -> engines [n ])
1652
1757
copy -> engines [n ] = intel_context_get (e -> engines [n ]);
@@ -1890,7 +1995,8 @@ static int clone_engines(struct i915_gem_context *dst,
1890
1995
if (!clone )
1891
1996
goto err_unlock ;
1892
1997
1893
- init_rcu_head (& clone -> rcu );
1998
+ clone -> ctx = dst ;
1999
+
1894
2000
for (n = 0 ; n < e -> num_engines ; n ++ ) {
1895
2001
struct intel_engine_cs * engine ;
1896
2002
0 commit comments