@@ -28,8 +28,9 @@ static int program_rcvarray(struct hfi1_filedata *fd, struct tid_user_buf *,
28
28
unsigned int start , u16 count ,
29
29
u32 * tidlist , unsigned int * tididx ,
30
30
unsigned int * pmapped );
31
- static int unprogram_rcvarray (struct hfi1_filedata * fd , u32 tidinfo ,
32
- struct tid_group * * grp );
31
+ static int unprogram_rcvarray (struct hfi1_filedata * fd , u32 tidinfo );
32
+ static void __clear_tid_node (struct hfi1_filedata * fd ,
33
+ struct tid_rb_node * node );
33
34
static void clear_tid_node (struct hfi1_filedata * fd , struct tid_rb_node * node );
34
35
35
36
static const struct mmu_interval_notifier_ops tid_mn_ops = {
@@ -469,7 +470,7 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
469
470
470
471
mutex_lock (& uctxt -> exp_mutex );
471
472
for (tididx = 0 ; tididx < tinfo -> tidcnt ; tididx ++ ) {
472
- ret = unprogram_rcvarray (fd , tidinfo [tididx ], NULL );
473
+ ret = unprogram_rcvarray (fd , tidinfo [tididx ]);
473
474
if (ret ) {
474
475
hfi1_cdbg (TID , "Failed to unprogram rcv array %d" ,
475
476
ret );
@@ -723,6 +724,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
723
724
}
724
725
725
726
node -> fdata = fd ;
727
+ mutex_init (& node -> invalidate_mutex );
726
728
node -> phys = page_to_phys (pages [0 ]);
727
729
node -> npages = npages ;
728
730
node -> rcventry = rcventry ;
@@ -762,8 +764,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
762
764
return - EFAULT ;
763
765
}
764
766
765
- static int unprogram_rcvarray (struct hfi1_filedata * fd , u32 tidinfo ,
766
- struct tid_group * * grp )
767
+ static int unprogram_rcvarray (struct hfi1_filedata * fd , u32 tidinfo )
767
768
{
768
769
struct hfi1_ctxtdata * uctxt = fd -> uctxt ;
769
770
struct hfi1_devdata * dd = uctxt -> dd ;
@@ -786,33 +787,41 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
786
787
if (!node || node -> rcventry != (uctxt -> expected_base + rcventry ))
787
788
return - EBADF ;
788
789
789
- if (grp )
790
- * grp = node -> grp ;
791
-
792
790
if (fd -> use_mn )
793
791
mmu_interval_notifier_remove (& node -> notifier );
794
792
cacheless_tid_rb_remove (fd , node );
795
793
796
794
return 0 ;
797
795
}
798
796
799
- static void clear_tid_node (struct hfi1_filedata * fd , struct tid_rb_node * node )
797
+ static void __clear_tid_node (struct hfi1_filedata * fd , struct tid_rb_node * node )
800
798
{
801
799
struct hfi1_ctxtdata * uctxt = fd -> uctxt ;
802
800
struct hfi1_devdata * dd = uctxt -> dd ;
803
801
802
+ mutex_lock (& node -> invalidate_mutex );
803
+ if (node -> freed )
804
+ goto done ;
805
+ node -> freed = true;
806
+
804
807
trace_hfi1_exp_tid_unreg (uctxt -> ctxt , fd -> subctxt , node -> rcventry ,
805
808
node -> npages ,
806
809
node -> notifier .interval_tree .start , node -> phys ,
807
810
node -> dma_addr );
808
811
809
- /*
810
- * Make sure device has seen the write before we unpin the
811
- * pages.
812
- */
812
+ /* Make sure device has seen the write before pages are unpinned */
813
813
hfi1_put_tid (dd , node -> rcventry , PT_INVALID_FLUSH , 0 , 0 );
814
814
815
815
unpin_rcv_pages (fd , NULL , node , 0 , node -> npages , true);
816
+ done :
817
+ mutex_unlock (& node -> invalidate_mutex );
818
+ }
819
+
820
+ static void clear_tid_node (struct hfi1_filedata * fd , struct tid_rb_node * node )
821
+ {
822
+ struct hfi1_ctxtdata * uctxt = fd -> uctxt ;
823
+
824
+ __clear_tid_node (fd , node );
816
825
817
826
node -> grp -> used -- ;
818
827
node -> grp -> map &= ~(1 << (node -> rcventry - node -> grp -> base ));
@@ -871,10 +880,16 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
871
880
if (node -> freed )
872
881
return true;
873
882
883
+ /* take action only if unmapping */
884
+ if (range -> event != MMU_NOTIFY_UNMAP )
885
+ return true;
886
+
874
887
trace_hfi1_exp_tid_inval (uctxt -> ctxt , fdata -> subctxt ,
875
888
node -> notifier .interval_tree .start ,
876
889
node -> rcventry , node -> npages , node -> dma_addr );
877
- node -> freed = true;
890
+
891
+ /* clear the hardware rcvarray entry */
892
+ __clear_tid_node (fdata , node );
878
893
879
894
spin_lock (& fdata -> invalid_lock );
880
895
if (fdata -> invalid_tid_idx < uctxt -> expected_count ) {
0 commit comments