@@ -242,7 +242,6 @@ static void __free_engines(struct i915_gem_engines *e, unsigned int count)
242
242
if (!e -> engines [count ])
243
243
continue ;
244
244
245
- RCU_INIT_POINTER (e -> engines [count ]-> gem_context , NULL );
246
245
intel_context_put (e -> engines [count ]);
247
246
}
248
247
kfree (e );
@@ -255,7 +254,11 @@ static void free_engines(struct i915_gem_engines *e)
255
254
256
255
static void free_engines_rcu (struct rcu_head * rcu )
257
256
{
258
- free_engines (container_of (rcu , struct i915_gem_engines , rcu ));
257
+ struct i915_gem_engines * engines =
258
+ container_of (rcu , struct i915_gem_engines , rcu );
259
+
260
+ i915_sw_fence_fini (& engines -> fence );
261
+ free_engines (engines );
259
262
}
260
263
261
264
static struct i915_gem_engines * default_engines (struct i915_gem_context * ctx )
@@ -269,8 +272,6 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
269
272
if (!e )
270
273
return ERR_PTR (- ENOMEM );
271
274
272
- e -> ctx = ctx ;
273
-
274
275
for_each_engine (engine , gt , id ) {
275
276
struct intel_context * ce ;
276
277
@@ -304,7 +305,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
304
305
list_del (& ctx -> link );
305
306
spin_unlock (& ctx -> i915 -> gem .contexts .lock );
306
307
307
- free_engines (rcu_access_pointer (ctx -> engines ));
308
308
mutex_destroy (& ctx -> engines_mutex );
309
309
310
310
if (ctx -> timeline )
@@ -491,30 +491,104 @@ static void kill_engines(struct i915_gem_engines *engines)
491
491
static void kill_stale_engines (struct i915_gem_context * ctx )
492
492
{
493
493
struct i915_gem_engines * pos , * next ;
494
- unsigned long flags ;
495
494
496
- spin_lock_irqsave (& ctx -> stale .lock , flags );
495
+ spin_lock_irq (& ctx -> stale .lock );
496
+ GEM_BUG_ON (!i915_gem_context_is_closed (ctx ));
497
497
list_for_each_entry_safe (pos , next , & ctx -> stale .engines , link ) {
498
- if (!i915_sw_fence_await (& pos -> fence ))
498
+ if (!i915_sw_fence_await (& pos -> fence )) {
499
+ list_del_init (& pos -> link );
499
500
continue ;
501
+ }
500
502
501
- spin_unlock_irqrestore (& ctx -> stale .lock , flags );
503
+ spin_unlock_irq (& ctx -> stale .lock );
502
504
503
505
kill_engines (pos );
504
506
505
- spin_lock_irqsave (& ctx -> stale .lock , flags );
507
+ spin_lock_irq (& ctx -> stale .lock );
508
+ GEM_BUG_ON (i915_sw_fence_signaled (& pos -> fence ));
506
509
list_safe_reset_next (pos , next , link );
507
510
list_del_init (& pos -> link ); /* decouple from FENCE_COMPLETE */
508
511
509
512
i915_sw_fence_complete (& pos -> fence );
510
513
}
511
- spin_unlock_irqrestore (& ctx -> stale .lock , flags );
514
+ spin_unlock_irq (& ctx -> stale .lock );
512
515
}
513
516
514
517
static void kill_context (struct i915_gem_context * ctx )
515
518
{
516
519
kill_stale_engines (ctx );
517
- kill_engines (__context_engines_static (ctx ));
520
+ }
521
+
522
+ static int engines_notify (struct i915_sw_fence * fence ,
523
+ enum i915_sw_fence_notify state )
524
+ {
525
+ struct i915_gem_engines * engines =
526
+ container_of (fence , typeof (* engines ), fence );
527
+
528
+ switch (state ) {
529
+ case FENCE_COMPLETE :
530
+ if (!list_empty (& engines -> link )) {
531
+ struct i915_gem_context * ctx = engines -> ctx ;
532
+ unsigned long flags ;
533
+
534
+ spin_lock_irqsave (& ctx -> stale .lock , flags );
535
+ list_del (& engines -> link );
536
+ spin_unlock_irqrestore (& ctx -> stale .lock , flags );
537
+ }
538
+ i915_gem_context_put (engines -> ctx );
539
+ break ;
540
+
541
+ case FENCE_FREE :
542
+ init_rcu_head (& engines -> rcu );
543
+ call_rcu (& engines -> rcu , free_engines_rcu );
544
+ break ;
545
+ }
546
+
547
+ return NOTIFY_DONE ;
548
+ }
549
+
550
+ static void engines_idle_release (struct i915_gem_context * ctx ,
551
+ struct i915_gem_engines * engines )
552
+ {
553
+ struct i915_gem_engines_iter it ;
554
+ struct intel_context * ce ;
555
+
556
+ i915_sw_fence_init (& engines -> fence , engines_notify );
557
+ INIT_LIST_HEAD (& engines -> link );
558
+
559
+ engines -> ctx = i915_gem_context_get (ctx );
560
+
561
+ for_each_gem_engine (ce , engines , it ) {
562
+ struct dma_fence * fence ;
563
+ int err = 0 ;
564
+
565
+ /* serialises with execbuf */
566
+ RCU_INIT_POINTER (ce -> gem_context , NULL );
567
+ if (!intel_context_pin_if_active (ce ))
568
+ continue ;
569
+
570
+ fence = i915_active_fence_get (& ce -> timeline -> last_request );
571
+ if (fence ) {
572
+ err = i915_sw_fence_await_dma_fence (& engines -> fence ,
573
+ fence , 0 ,
574
+ GFP_KERNEL );
575
+ dma_fence_put (fence );
576
+ }
577
+ intel_context_unpin (ce );
578
+ if (err < 0 )
579
+ goto kill ;
580
+ }
581
+
582
+ spin_lock_irq (& ctx -> stale .lock );
583
+ if (!i915_gem_context_is_closed (ctx ))
584
+ list_add_tail (& engines -> link , & ctx -> stale .engines );
585
+ spin_unlock_irq (& ctx -> stale .lock );
586
+
587
+ kill :
588
+ if (list_empty (& engines -> link )) /* raced, already closed */
589
+ kill_engines (engines );
590
+
591
+ i915_sw_fence_commit (& engines -> fence );
518
592
}
519
593
520
594
static void set_closed_name (struct i915_gem_context * ctx )
@@ -538,11 +612,16 @@ static void context_close(struct i915_gem_context *ctx)
538
612
{
539
613
struct i915_address_space * vm ;
540
614
615
+ /* Flush any concurrent set_engines() */
616
+ mutex_lock (& ctx -> engines_mutex );
617
+ engines_idle_release (ctx , rcu_replace_pointer (ctx -> engines , NULL , 1 ));
541
618
i915_gem_context_set_closed (ctx );
542
- set_closed_name ( ctx );
619
+ mutex_unlock ( & ctx -> engines_mutex );
543
620
544
621
mutex_lock (& ctx -> mutex );
545
622
623
+ set_closed_name (ctx );
624
+
546
625
vm = i915_gem_context_vm (ctx );
547
626
if (vm )
548
627
i915_vm_close (vm );
@@ -1626,77 +1705,6 @@ static const i915_user_extension_fn set_engines__extensions[] = {
1626
1705
[I915_CONTEXT_ENGINES_EXT_BOND ] = set_engines__bond ,
1627
1706
};
1628
1707
1629
- static int engines_notify (struct i915_sw_fence * fence ,
1630
- enum i915_sw_fence_notify state )
1631
- {
1632
- struct i915_gem_engines * engines =
1633
- container_of (fence , typeof (* engines ), fence );
1634
-
1635
- switch (state ) {
1636
- case FENCE_COMPLETE :
1637
- if (!list_empty (& engines -> link )) {
1638
- struct i915_gem_context * ctx = engines -> ctx ;
1639
- unsigned long flags ;
1640
-
1641
- spin_lock_irqsave (& ctx -> stale .lock , flags );
1642
- list_del (& engines -> link );
1643
- spin_unlock_irqrestore (& ctx -> stale .lock , flags );
1644
- }
1645
- break ;
1646
-
1647
- case FENCE_FREE :
1648
- init_rcu_head (& engines -> rcu );
1649
- call_rcu (& engines -> rcu , free_engines_rcu );
1650
- break ;
1651
- }
1652
-
1653
- return NOTIFY_DONE ;
1654
- }
1655
-
1656
- static void engines_idle_release (struct i915_gem_engines * engines )
1657
- {
1658
- struct i915_gem_engines_iter it ;
1659
- struct intel_context * ce ;
1660
- unsigned long flags ;
1661
-
1662
- GEM_BUG_ON (!engines );
1663
- i915_sw_fence_init (& engines -> fence , engines_notify );
1664
-
1665
- INIT_LIST_HEAD (& engines -> link );
1666
- spin_lock_irqsave (& engines -> ctx -> stale .lock , flags );
1667
- if (!i915_gem_context_is_closed (engines -> ctx ))
1668
- list_add (& engines -> link , & engines -> ctx -> stale .engines );
1669
- spin_unlock_irqrestore (& engines -> ctx -> stale .lock , flags );
1670
- if (list_empty (& engines -> link )) /* raced, already closed */
1671
- goto kill ;
1672
-
1673
- for_each_gem_engine (ce , engines , it ) {
1674
- struct dma_fence * fence ;
1675
- int err ;
1676
-
1677
- if (!ce -> timeline )
1678
- continue ;
1679
-
1680
- fence = i915_active_fence_get (& ce -> timeline -> last_request );
1681
- if (!fence )
1682
- continue ;
1683
-
1684
- err = i915_sw_fence_await_dma_fence (& engines -> fence ,
1685
- fence , 0 ,
1686
- GFP_KERNEL );
1687
-
1688
- dma_fence_put (fence );
1689
- if (err < 0 )
1690
- goto kill ;
1691
- }
1692
- goto out ;
1693
-
1694
- kill :
1695
- kill_engines (engines );
1696
- out :
1697
- i915_sw_fence_commit (& engines -> fence );
1698
- }
1699
-
1700
1708
static int
1701
1709
set_engines (struct i915_gem_context * ctx ,
1702
1710
const struct drm_i915_gem_context_param * args )
@@ -1739,8 +1747,6 @@ set_engines(struct i915_gem_context *ctx,
1739
1747
if (!set .engines )
1740
1748
return - ENOMEM ;
1741
1749
1742
- set .engines -> ctx = ctx ;
1743
-
1744
1750
for (n = 0 ; n < num_engines ; n ++ ) {
1745
1751
struct i915_engine_class_instance ci ;
1746
1752
struct intel_engine_cs * engine ;
@@ -1793,6 +1799,11 @@ set_engines(struct i915_gem_context *ctx,
1793
1799
1794
1800
replace :
1795
1801
mutex_lock (& ctx -> engines_mutex );
1802
+ if (i915_gem_context_is_closed (ctx )) {
1803
+ mutex_unlock (& ctx -> engines_mutex );
1804
+ free_engines (set .engines );
1805
+ return - ENOENT ;
1806
+ }
1796
1807
if (args -> size )
1797
1808
i915_gem_context_set_user_engines (ctx );
1798
1809
else
@@ -1801,7 +1812,7 @@ set_engines(struct i915_gem_context *ctx,
1801
1812
mutex_unlock (& ctx -> engines_mutex );
1802
1813
1803
1814
/* Keep track of old engine sets for kill_context() */
1804
- engines_idle_release (set .engines );
1815
+ engines_idle_release (ctx , set .engines );
1805
1816
1806
1817
return 0 ;
1807
1818
}
@@ -2077,8 +2088,6 @@ static int clone_engines(struct i915_gem_context *dst,
2077
2088
if (!clone )
2078
2089
goto err_unlock ;
2079
2090
2080
- clone -> ctx = dst ;
2081
-
2082
2091
for (n = 0 ; n < e -> num_engines ; n ++ ) {
2083
2092
struct intel_engine_cs * engine ;
2084
2093
@@ -2121,8 +2130,7 @@ static int clone_engines(struct i915_gem_context *dst,
2121
2130
i915_gem_context_unlock_engines (src );
2122
2131
2123
2132
/* Serialised by constructor */
2124
- free_engines (__context_engines_static (dst ));
2125
- RCU_INIT_POINTER (dst -> engines , clone );
2133
+ engines_idle_release (dst , rcu_replace_pointer (dst -> engines , clone , 1 ));
2126
2134
if (user_engines )
2127
2135
i915_gem_context_set_user_engines (dst );
2128
2136
else
@@ -2553,6 +2561,9 @@ i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
2553
2561
const struct i915_gem_engines * e = it -> engines ;
2554
2562
struct intel_context * ctx ;
2555
2563
2564
+ if (unlikely (!e ))
2565
+ return NULL ;
2566
+
2556
2567
do {
2557
2568
if (it -> idx >= e -> num_engines )
2558
2569
return NULL ;
0 commit comments