Commit 4f564ff3 authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Jason Gunthorpe
Browse files

drivers/mic/scif: do not use mmap_sem



The driver uses mmap_sem for both pinned_vm accounting and
get_user_pages(). By using gup_fast() and letting the mm handle the lock
if needed, we can no longer rely on the semaphore and simplify the whole
thing.

Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarDavidlohr Bueso <dbueso@suse.de>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 70f8a3ca
Loading
Loading
Loading
Loading
+11 −25
Original line number Diff line number Diff line
@@ -272,21 +272,12 @@ static inline void __scif_release_mm(struct mm_struct *mm)

static inline int
__scif_dec_pinned_vm_lock(struct mm_struct *mm,
			  int nr_pages, bool try_lock)
			  int nr_pages)
{
	if (!mm || !nr_pages || !scif_ulimit_check)
		return 0;
	if (try_lock) {
		if (!down_write_trylock(&mm->mmap_sem)) {
			dev_err(scif_info.mdev.this_device,
				"%s %d err\n", __func__, __LINE__);
			return -1;
		}
	} else {
		down_write(&mm->mmap_sem);
	}

	atomic64_sub(nr_pages, &mm->pinned_vm);
	up_write(&mm->mmap_sem);
	return 0;
}

@@ -298,16 +289,16 @@ static inline int __scif_check_inc_pinned_vm(struct mm_struct *mm,
	if (!mm || !nr_pages || !scif_ulimit_check)
		return 0;

	locked = nr_pages;
	locked += atomic64_read(&mm->pinned_vm);
	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
	locked = atomic64_add_return(nr_pages, &mm->pinned_vm);

	if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
		atomic64_sub(nr_pages, &mm->pinned_vm);
		dev_err(scif_info.mdev.this_device,
			"locked(%lu) > lock_limit(%lu)\n",
			locked, lock_limit);
		return -ENOMEM;
	}
	atomic64_set(&mm->pinned_vm, locked);
	return 0;
}

@@ -326,7 +317,7 @@ int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window)

	might_sleep();
	if (!window->temp && window->mm) {
		__scif_dec_pinned_vm_lock(window->mm, window->nr_pages, 0);
		__scif_dec_pinned_vm_lock(window->mm, window->nr_pages);
		__scif_release_mm(window->mm);
		window->mm = NULL;
	}
@@ -737,7 +728,7 @@ done:
					    ep->rma_info.dma_chan);
		} else {
			if (!__scif_dec_pinned_vm_lock(window->mm,
						       window->nr_pages, 1)) {
						       window->nr_pages)) {
				__scif_release_mm(window->mm);
				window->mm = NULL;
			}
@@ -1385,28 +1376,23 @@ int __scif_pin_pages(void *addr, size_t len, int *out_prot,
		prot |= SCIF_PROT_WRITE;
retry:
		mm = current->mm;
		down_write(&mm->mmap_sem);
		if (ulimit) {
			err = __scif_check_inc_pinned_vm(mm, nr_pages);
			if (err) {
				up_write(&mm->mmap_sem);
				pinned_pages->nr_pages = 0;
				goto error_unmap;
			}
		}

		pinned_pages->nr_pages = get_user_pages(
		pinned_pages->nr_pages = get_user_pages_fast(
				(u64)addr,
				nr_pages,
				(prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
				pinned_pages->pages,
				NULL);
		up_write(&mm->mmap_sem);
				pinned_pages->pages);
		if (nr_pages != pinned_pages->nr_pages) {
			if (try_upgrade) {
				if (ulimit)
					__scif_dec_pinned_vm_lock(mm,
								  nr_pages, 0);
					__scif_dec_pinned_vm_lock(mm, nr_pages);
				/* Roll back any pinned pages */
				for (i = 0; i < pinned_pages->nr_pages; i++) {
					if (pinned_pages->pages[i])
@@ -1433,7 +1419,7 @@ retry:
	return err;
dec_pinned:
	if (ulimit)
		__scif_dec_pinned_vm_lock(mm, nr_pages, 0);
		__scif_dec_pinned_vm_lock(mm, nr_pages);
	/* Something went wrong! Rollback */
error_unmap:
	pinned_pages->nr_pages = nr_pages;