@@ -488,12 +488,16 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
488
488
ttm_bo_mem_put (bo , & bo -> mem );
489
489
490
490
atomic_set (& bo -> reserved , 0 );
491
+ wake_up_all (& bo -> event_queue );
491
492
492
493
/*
493
- * Make processes trying to reserve really pick it up.
494
+ * Since the final reference to this bo may not be dropped by
495
+ * the current task we have to put a memory barrier here to make
496
+ * sure the changes done in this function are always visible.
497
+ *
498
+ * This function only needs protection against the final kref_put.
494
499
*/
495
- smp_mb__after_atomic_dec ();
496
- wake_up_all (& bo -> event_queue );
500
+ smp_mb__before_atomic_dec ();
497
501
}
498
502
499
503
static void ttm_bo_cleanup_refs_or_queue (struct ttm_buffer_object * bo )
@@ -543,68 +547,84 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
543
547
}
544
548
545
549
/**
546
- * function ttm_bo_cleanup_refs
550
+ * function ttm_bo_cleanup_refs_and_unlock
547
551
* If bo idle, remove from delayed- and lru lists, and unref.
548
552
* If not idle, do nothing.
549
553
*
554
+ * Must be called with lru_lock and reservation held, this function
555
+ * will drop both before returning.
556
+ *
550
557
* @interruptible Any sleeps should occur interruptibly.
551
- * @no_wait_reserve Never wait for reserve. Return -EBUSY instead.
552
558
* @no_wait_gpu Never wait for gpu. Return -EBUSY instead.
553
559
*/
554
560
555
- static int ttm_bo_cleanup_refs (struct ttm_buffer_object * bo ,
556
- bool interruptible ,
557
- bool no_wait_reserve ,
558
- bool no_wait_gpu )
561
+ static int ttm_bo_cleanup_refs_and_unlock (struct ttm_buffer_object * bo ,
562
+ bool interruptible ,
563
+ bool no_wait_gpu )
559
564
{
560
565
struct ttm_bo_device * bdev = bo -> bdev ;
566
+ struct ttm_bo_driver * driver = bdev -> driver ;
561
567
struct ttm_bo_global * glob = bo -> glob ;
562
568
int put_count ;
563
- int ret = 0 ;
569
+ int ret ;
564
570
565
- retry :
566
571
spin_lock (& bdev -> fence_lock );
567
- ret = ttm_bo_wait (bo , false, interruptible , no_wait_gpu );
568
- spin_unlock (& bdev -> fence_lock );
572
+ ret = ttm_bo_wait (bo , false, false, true);
569
573
570
- if (unlikely ( ret != 0 ))
571
- return ret ;
574
+ if (ret && ! no_wait_gpu ) {
575
+ void * sync_obj ;
572
576
573
- retry_reserve :
574
- spin_lock (& glob -> lru_lock );
577
+ /*
578
+ * Take a reference to the fence and unreserve,
579
+ * at this point the buffer should be dead, so
580
+ * no new sync objects can be attached.
581
+ */
582
+ sync_obj = driver -> sync_obj_ref (& bo -> sync_obj );
583
+ spin_unlock (& bdev -> fence_lock );
575
584
576
- if (unlikely (list_empty (& bo -> ddestroy ))) {
585
+ atomic_set (& bo -> reserved , 0 );
586
+ wake_up_all (& bo -> event_queue );
577
587
spin_unlock (& glob -> lru_lock );
578
- return 0 ;
579
- }
580
588
581
- ret = ttm_bo_reserve_locked (bo , false, true, false, 0 );
582
-
583
- if (unlikely (ret == - EBUSY )) {
584
- spin_unlock (& glob -> lru_lock );
585
- if (likely (!no_wait_reserve ))
586
- ret = ttm_bo_wait_unreserved (bo , interruptible );
587
- if (unlikely (ret != 0 ))
589
+ ret = driver -> sync_obj_wait (sync_obj , false, interruptible );
590
+ driver -> sync_obj_unref (& sync_obj );
591
+ if (ret )
588
592
return ret ;
589
593
590
- goto retry_reserve ;
591
- }
594
+ /*
595
+ * remove sync_obj with ttm_bo_wait, the wait should be
596
+ * finished, and no new wait object should have been added.
597
+ */
598
+ spin_lock (& bdev -> fence_lock );
599
+ ret = ttm_bo_wait (bo , false, false, true);
600
+ WARN_ON (ret );
601
+ spin_unlock (& bdev -> fence_lock );
602
+ if (ret )
603
+ return ret ;
592
604
593
- BUG_ON (ret != 0 );
605
+ spin_lock (& glob -> lru_lock );
606
+ ret = ttm_bo_reserve_locked (bo , false, true, false, 0 );
594
607
595
- /**
596
- * We can re-check for sync object without taking
597
- * the bo::lock since setting the sync object requires
598
- * also bo::reserved. A busy object at this point may
599
- * be caused by another thread recently starting an accelerated
600
- * eviction.
601
- */
608
+ /*
609
+ * We raced, and lost, someone else holds the reservation now,
610
+ * and is probably busy in ttm_bo_cleanup_memtype_use.
611
+ *
612
+ * Even if it's not the case, because we finished waiting any
613
+ * delayed destruction would succeed, so just return success
614
+ * here.
615
+ */
616
+ if (ret ) {
617
+ spin_unlock (& glob -> lru_lock );
618
+ return 0 ;
619
+ }
620
+ } else
621
+ spin_unlock (& bdev -> fence_lock );
602
622
603
- if (unlikely (bo -> sync_obj )) {
623
+ if (ret || unlikely (list_empty ( & bo -> ddestroy ) )) {
604
624
atomic_set (& bo -> reserved , 0 );
605
625
wake_up_all (& bo -> event_queue );
606
626
spin_unlock (& glob -> lru_lock );
607
- goto retry ;
627
+ return ret ;
608
628
}
609
629
610
630
put_count = ttm_bo_del_from_lru (bo );
@@ -647,9 +667,13 @@ static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
647
667
kref_get (& nentry -> list_kref );
648
668
}
649
669
650
- spin_unlock (& glob -> lru_lock );
651
- ret = ttm_bo_cleanup_refs (entry , false, !remove_all ,
652
- !remove_all );
670
+ ret = ttm_bo_reserve_locked (entry , false, !remove_all , false, 0 );
671
+ if (!ret )
672
+ ret = ttm_bo_cleanup_refs_and_unlock (entry , false,
673
+ !remove_all );
674
+ else
675
+ spin_unlock (& glob -> lru_lock );
676
+
653
677
kref_put (& entry -> list_kref , ttm_bo_release_list );
654
678
entry = nentry ;
655
679
@@ -800,9 +824,13 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
800
824
kref_get (& bo -> list_kref );
801
825
802
826
if (!list_empty (& bo -> ddestroy )) {
803
- spin_unlock (& glob -> lru_lock );
804
- ret = ttm_bo_cleanup_refs (bo , interruptible ,
805
- no_wait_reserve , no_wait_gpu );
827
+ ret = ttm_bo_reserve_locked (bo , interruptible , no_wait_reserve , false, 0 );
828
+ if (!ret )
829
+ ret = ttm_bo_cleanup_refs_and_unlock (bo , interruptible ,
830
+ no_wait_gpu );
831
+ else
832
+ spin_unlock (& glob -> lru_lock );
833
+
806
834
kref_put (& bo -> list_kref , ttm_bo_release_list );
807
835
808
836
return ret ;
@@ -1796,8 +1824,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
1796
1824
kref_get (& bo -> list_kref );
1797
1825
1798
1826
if (!list_empty (& bo -> ddestroy )) {
1799
- spin_unlock (& glob -> lru_lock );
1800
- (void ) ttm_bo_cleanup_refs (bo , false, false, false);
1827
+ ttm_bo_reserve_locked (bo , false, false, false, 0 );
1828
+ ttm_bo_cleanup_refs_and_unlock (bo , false, false);
1829
+
1801
1830
kref_put (& bo -> list_kref , ttm_bo_release_list );
1802
1831
spin_lock (& glob -> lru_lock );
1803
1832
continue ;
0 commit comments