Skip to content

Commit def8228

Browse files
dhharalagregkh
authored andcommitted
staging/rdma/hfi1: Convert to use get_user_pages_fast
Convert hfi1_get_user_pages() to use get_user_pages_fast(), which is much fatster. The mm semaphore is still taken to update the pinned page count but is for a much shorter amount of time. Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 483119a commit def8228

File tree

3 files changed

+32
-77
lines changed

3 files changed

+32
-77
lines changed

drivers/staging/rdma/hfi1/file_ops.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,8 +1663,8 @@ static int exp_tid_setup(struct file *fp, struct hfi1_tid_info *tinfo)
16631663
* Now that we know how many free RcvArray entries we have,
16641664
* we can pin that many user pages.
16651665
*/
1666-
ret = hfi1_get_user_pages(vaddr + (mapped * PAGE_SIZE),
1667-
pinned, pages);
1666+
ret = hfi1_acquire_user_pages(vaddr + (mapped * PAGE_SIZE),
1667+
pinned, true, pages);
16681668
if (ret) {
16691669
/*
16701670
* We can't continue because the pages array won't be
@@ -1833,7 +1833,7 @@ static int exp_tid_free(struct file *fp, struct hfi1_tid_info *tinfo)
18331833
}
18341834
}
18351835
flush_wc();
1836-
hfi1_release_user_pages(pshadow, pcount);
1836+
hfi1_release_user_pages(pshadow, pcount, true);
18371837
clear_bit(bitidx, &uctxt->tidusemap[idx]);
18381838
map &= ~(1ULL<<bitidx);
18391839
}
@@ -1862,7 +1862,7 @@ static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt)
18621862
uctxt->physshadow[tid] = 0;
18631863
uctxt->tid_pg_list[tid] = NULL;
18641864
pci_unmap_page(dd->pcidev, phys, PAGE_SIZE, PCI_DMA_FROMDEVICE);
1865-
hfi1_release_user_pages(&p, 1);
1865+
hfi1_release_user_pages(&p, 1, true);
18661866
}
18671867
}
18681868

drivers/staging/rdma/hfi1/hfi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,8 +1587,8 @@ void hfi1_set_led_override(struct hfi1_pportdata *ppd, unsigned int val);
15871587
*/
15881588
#define DEFAULT_RCVHDR_ENTSIZE 32
15891589

1590-
int hfi1_get_user_pages(unsigned long, size_t, struct page **);
1591-
void hfi1_release_user_pages(struct page **, size_t);
1590+
int hfi1_acquire_user_pages(unsigned long, size_t, bool, struct page **);
1591+
void hfi1_release_user_pages(struct page **, size_t, bool);
15921592

15931593
static inline void clear_rcvhdrtail(const struct hfi1_ctxtdata *rcd)
15941594
{

drivers/staging/rdma/hfi1/user_pages.c

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -49,59 +49,11 @@
4949
*/
5050

5151
#include <linux/mm.h>
52+
#include <linux/sched.h>
5253
#include <linux/device.h>
5354

5455
#include "hfi.h"
5556

56-
static void __hfi1_release_user_pages(struct page **p, size_t num_pages,
57-
int dirty)
58-
{
59-
size_t i;
60-
61-
for (i = 0; i < num_pages; i++) {
62-
if (dirty)
63-
set_page_dirty_lock(p[i]);
64-
put_page(p[i]);
65-
}
66-
}
67-
68-
/*
69-
* Call with current->mm->mmap_sem held.
70-
*/
71-
static int __hfi1_get_user_pages(unsigned long start_page, size_t num_pages,
72-
struct page **p)
73-
{
74-
unsigned long lock_limit;
75-
size_t got;
76-
int ret;
77-
78-
lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
79-
80-
if (num_pages > lock_limit && !capable(CAP_IPC_LOCK)) {
81-
ret = -ENOMEM;
82-
goto bail;
83-
}
84-
85-
for (got = 0; got < num_pages; got += ret) {
86-
ret = get_user_pages(current, current->mm,
87-
start_page + got * PAGE_SIZE,
88-
num_pages - got, 1, 1,
89-
p + got, NULL);
90-
if (ret < 0)
91-
goto bail_release;
92-
}
93-
94-
current->mm->pinned_vm += num_pages;
95-
96-
ret = 0;
97-
goto bail;
98-
99-
bail_release:
100-
__hfi1_release_user_pages(p, got, 0);
101-
bail:
102-
return ret;
103-
}
104-
10557
/**
10658
* hfi1_map_page - a safety wrapper around pci_map_page()
10759
*
@@ -116,41 +68,44 @@ dma_addr_t hfi1_map_page(struct pci_dev *hwdev, struct page *page,
11668
return phys;
11769
}
11870

119-
/**
120-
* hfi1_get_user_pages - lock user pages into memory
121-
* @start_page: the start page
122-
* @num_pages: the number of pages
123-
* @p: the output page structures
124-
*
125-
* This function takes a given start page (page aligned user virtual
126-
* address) and pins it and the following specified number of pages. For
127-
* now, num_pages is always 1, but that will probably change at some point
128-
* (because caller is doing expected sends on a single virtually contiguous
129-
* buffer, so we can do all pages at once).
130-
*/
131-
int hfi1_get_user_pages(unsigned long start_page, size_t num_pages,
132-
struct page **p)
71+
int hfi1_acquire_user_pages(unsigned long vaddr, size_t npages, bool writable,
72+
struct page **pages)
13373
{
74+
unsigned long pinned, lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
75+
bool can_lock = capable(CAP_IPC_LOCK);
13476
int ret;
13577

136-
down_write(&current->mm->mmap_sem);
78+
down_read(&current->mm->mmap_sem);
79+
pinned = current->mm->pinned_vm;
80+
up_read(&current->mm->mmap_sem);
13781

138-
ret = __hfi1_get_user_pages(start_page, num_pages, p);
82+
if (pinned + npages > lock_limit && !can_lock)
83+
return -ENOMEM;
13984

85+
ret = get_user_pages_fast(vaddr, npages, writable, pages);
86+
if (ret < 0)
87+
return ret;
88+
89+
down_write(&current->mm->mmap_sem);
90+
current->mm->pinned_vm += ret;
14091
up_write(&current->mm->mmap_sem);
14192

14293
return ret;
14394
}
14495

145-
void hfi1_release_user_pages(struct page **p, size_t num_pages)
96+
void hfi1_release_user_pages(struct page **p, size_t npages, bool dirty)
14697
{
147-
if (current->mm) /* during close after signal, mm can be NULL */
148-
down_write(&current->mm->mmap_sem);
98+
size_t i;
14999

150-
__hfi1_release_user_pages(p, num_pages, 1);
100+
for (i = 0; i < npages; i++) {
101+
if (dirty)
102+
set_page_dirty_lock(p[i]);
103+
put_page(p[i]);
104+
}
151105

152-
if (current->mm) {
153-
current->mm->pinned_vm -= num_pages;
106+
if (current->mm) { /* during close after signal, mm can be NULL */
107+
down_write(&current->mm->mmap_sem);
108+
current->mm->pinned_vm -= npages;
154109
up_write(&current->mm->mmap_sem);
155110
}
156111
}

0 commit comments

Comments
 (0)