@@ -28,8 +28,9 @@ static int program_rcvarray(struct hfi1_filedata *fd, struct tid_user_buf *,
2828 unsigned int start , u16 count ,
2929 u32 * tidlist , unsigned int * tididx ,
3030 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 );
3334static void clear_tid_node (struct hfi1_filedata * fd , struct tid_rb_node * node );
3435
3536static const struct mmu_interval_notifier_ops tid_mn_ops = {
@@ -469,7 +470,7 @@ int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
469470
470471 mutex_lock (& uctxt -> exp_mutex );
471472 for (tididx = 0 ; tididx < tinfo -> tidcnt ; tididx ++ ) {
472- ret = unprogram_rcvarray (fd , tidinfo [tididx ], NULL );
473+ ret = unprogram_rcvarray (fd , tidinfo [tididx ]);
473474 if (ret ) {
474475 hfi1_cdbg (TID , "Failed to unprogram rcv array %d" ,
475476 ret );
@@ -723,6 +724,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
723724 }
724725
725726 node -> fdata = fd ;
727+ mutex_init (& node -> invalidate_mutex );
726728 node -> phys = page_to_phys (pages [0 ]);
727729 node -> npages = npages ;
728730 node -> rcventry = rcventry ;
@@ -762,8 +764,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
762764 return - EFAULT ;
763765}
764766
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 )
767768{
768769 struct hfi1_ctxtdata * uctxt = fd -> uctxt ;
769770 struct hfi1_devdata * dd = uctxt -> dd ;
@@ -786,33 +787,41 @@ static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
786787 if (!node || node -> rcventry != (uctxt -> expected_base + rcventry ))
787788 return - EBADF ;
788789
789- if (grp )
790- * grp = node -> grp ;
791-
792790 if (fd -> use_mn )
793791 mmu_interval_notifier_remove (& node -> notifier );
794792 cacheless_tid_rb_remove (fd , node );
795793
796794 return 0 ;
797795}
798796
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 )
800798{
801799 struct hfi1_ctxtdata * uctxt = fd -> uctxt ;
802800 struct hfi1_devdata * dd = uctxt -> dd ;
803801
802+ mutex_lock (& node -> invalidate_mutex );
803+ if (node -> freed )
804+ goto done ;
805+ node -> freed = true;
806+
804807 trace_hfi1_exp_tid_unreg (uctxt -> ctxt , fd -> subctxt , node -> rcventry ,
805808 node -> npages ,
806809 node -> notifier .interval_tree .start , node -> phys ,
807810 node -> dma_addr );
808811
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 */
813813 hfi1_put_tid (dd , node -> rcventry , PT_INVALID_FLUSH , 0 , 0 );
814814
815815 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 );
816825
817826 node -> grp -> used -- ;
818827 node -> grp -> map &= ~(1 << (node -> rcventry - node -> grp -> base ));
@@ -871,10 +880,16 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
871880 if (node -> freed )
872881 return true;
873882
883+ /* take action only if unmapping */
884+ if (range -> event != MMU_NOTIFY_UNMAP )
885+ return true;
886+
874887 trace_hfi1_exp_tid_inval (uctxt -> ctxt , fdata -> subctxt ,
875888 node -> notifier .interval_tree .start ,
876889 node -> rcventry , node -> npages , node -> dma_addr );
877- node -> freed = true;
890+
891+ /* clear the hardware rcvarray entry */
892+ __clear_tid_node (fdata , node );
878893
879894 spin_lock (& fdata -> invalid_lock );
880895 if (fdata -> invalid_tid_idx < uctxt -> expected_count ) {
0 commit comments