@@ -23,6 +23,9 @@ static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
2323static bool tid_rb_invalidate (struct mmu_interval_notifier * mni ,
2424 const struct mmu_notifier_range * range ,
2525 unsigned long cur_seq );
26+ static bool tid_cover_invalidate (struct mmu_interval_notifier * mni ,
27+ const struct mmu_notifier_range * range ,
28+ unsigned long cur_seq );
2629static int program_rcvarray (struct hfi1_filedata * fd , struct tid_user_buf * ,
2730 struct tid_group * grp ,
2831 unsigned int start , u16 count ,
@@ -36,6 +39,9 @@ static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node);
3639static const struct mmu_interval_notifier_ops tid_mn_ops = {
3740 .invalidate = tid_rb_invalidate ,
3841};
42+ static const struct mmu_interval_notifier_ops tid_cover_ops = {
43+ .invalidate = tid_cover_invalidate ,
44+ };
3945
4046/*
4147 * Initialize context and file private data needed for Expected
@@ -254,6 +260,7 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
254260 tididx = 0 , mapped , mapped_pages = 0 ;
255261 u32 * tidlist = NULL ;
256262 struct tid_user_buf * tidbuf ;
263+ unsigned long mmu_seq = 0 ;
257264
258265 if (!PAGE_ALIGNED (tinfo -> vaddr ))
259266 return - EINVAL ;
@@ -264,6 +271,7 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
264271 if (!tidbuf )
265272 return - ENOMEM ;
266273
274+ mutex_init (& tidbuf -> cover_mutex );
267275 tidbuf -> vaddr = tinfo -> vaddr ;
268276 tidbuf -> length = tinfo -> length ;
269277 tidbuf -> psets = kcalloc (uctxt -> expected_count , sizeof (* tidbuf -> psets ),
@@ -273,6 +281,16 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
273281 goto fail_release_mem ;
274282 }
275283
284+ if (fd -> use_mn ) {
285+ ret = mmu_interval_notifier_insert (
286+ & tidbuf -> notifier , current -> mm ,
287+ tidbuf -> vaddr , tidbuf -> npages * PAGE_SIZE ,
288+ & tid_cover_ops );
289+ if (ret )
290+ goto fail_release_mem ;
291+ mmu_seq = mmu_interval_read_begin (& tidbuf -> notifier );
292+ }
293+
276294 pinned = pin_rcv_pages (fd , tidbuf );
277295 if (pinned <= 0 ) {
278296 ret = (pinned < 0 ) ? pinned : - ENOSPC ;
@@ -415,6 +433,20 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
415433 unpin_rcv_pages (fd , tidbuf , NULL , mapped_pages , pinned - mapped_pages ,
416434 false);
417435
436+ if (fd -> use_mn ) {
437+ /* check for an invalidate during setup */
438+ bool fail = false;
439+
440+ mutex_lock (& tidbuf -> cover_mutex );
441+ fail = mmu_interval_read_retry (& tidbuf -> notifier , mmu_seq );
442+ mutex_unlock (& tidbuf -> cover_mutex );
443+
444+ if (fail ) {
445+ ret = - EBUSY ;
446+ goto fail_unprogram ;
447+ }
448+ }
449+
418450 tinfo -> tidcnt = tididx ;
419451 tinfo -> length = mapped_pages * PAGE_SIZE ;
420452
@@ -424,6 +456,8 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
424456 goto fail_unprogram ;
425457 }
426458
459+ if (fd -> use_mn )
460+ mmu_interval_notifier_remove (& tidbuf -> notifier );
427461 kfree (tidbuf -> pages );
428462 kfree (tidbuf -> psets );
429463 kfree (tidbuf );
@@ -442,6 +476,8 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
442476 fd -> tid_used -= pageset_count ;
443477 spin_unlock (& fd -> tid_lock );
444478fail_unpin :
479+ if (fd -> use_mn )
480+ mmu_interval_notifier_remove (& tidbuf -> notifier );
445481 if (pinned > 0 )
446482 unpin_rcv_pages (fd , tidbuf , NULL , 0 , pinned , false);
447483fail_release_mem :
@@ -740,11 +776,6 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
740776 & tid_mn_ops );
741777 if (ret )
742778 goto out_unmap ;
743- /*
744- * FIXME: This is in the wrong order, the notifier should be
745- * established before the pages are pinned by pin_rcv_pages.
746- */
747- mmu_interval_read_begin (& node -> notifier );
748779 }
749780 fd -> entry_to_rb [node -> rcventry - uctxt -> expected_base ] = node ;
750781
@@ -919,6 +950,23 @@ static bool tid_rb_invalidate(struct mmu_interval_notifier *mni,
919950 return true;
920951}
921952
953+ static bool tid_cover_invalidate (struct mmu_interval_notifier * mni ,
954+ const struct mmu_notifier_range * range ,
955+ unsigned long cur_seq )
956+ {
957+ struct tid_user_buf * tidbuf =
958+ container_of (mni , struct tid_user_buf , notifier );
959+
960+ /* take action only if unmapping */
961+ if (range -> event == MMU_NOTIFY_UNMAP ) {
962+ mutex_lock (& tidbuf -> cover_mutex );
963+ mmu_interval_set_seq (mni , cur_seq );
964+ mutex_unlock (& tidbuf -> cover_mutex );
965+ }
966+
967+ return true;
968+ }
969+
922970static void cacheless_tid_rb_remove (struct hfi1_filedata * fdata ,
923971 struct tid_rb_node * tnode )
924972{
0 commit comments