aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/mm/gup.c12
-rw-r--r--arch/powerpc/mm/hugetlbpage.c21
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c1
-rw-r--r--arch/s390/mm/gup.c14
-rw-r--r--arch/sparc/mm/gup.c2
-rw-r--r--arch/x86/mm/gup.c10
6 files changed, 32 insertions, 28 deletions
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c
index fec13200868f..d7efdbf640c7 100644
--- a/arch/powerpc/mm/gup.c
+++ b/arch/powerpc/mm/gup.c
@@ -16,16 +16,6 @@
16 16
17#ifdef __HAVE_ARCH_PTE_SPECIAL 17#ifdef __HAVE_ARCH_PTE_SPECIAL
18 18
19static inline void get_huge_page_tail(struct page *page)
20{
21 /*
22 * __split_huge_page_refcount() cannot run
23 * from under us.
24 */
25 VM_BUG_ON(atomic_read(&page->_count) < 0);
26 atomic_inc(&page->_count);
27}
28
29/* 19/*
30 * The performance critical leaf functions are made noinline otherwise gcc 20 * The performance critical leaf functions are made noinline otherwise gcc
31 * inlines everything into a single function which results in too much 21 * inlines everything into a single function which results in too much
@@ -57,8 +47,6 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
57 put_page(page); 47 put_page(page);
58 return 0; 48 return 0;
59 } 49 }
60 if (PageTail(page))
61 get_huge_page_tail(page);
62 pages[*nr] = page; 50 pages[*nr] = page;
63 (*nr)++; 51 (*nr)++;
64 52
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0b9a5c1901b9..da5eb3885702 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -390,7 +390,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
390{ 390{
391 unsigned long mask; 391 unsigned long mask;
392 unsigned long pte_end; 392 unsigned long pte_end;
393 struct page *head, *page; 393 struct page *head, *page, *tail;
394 pte_t pte; 394 pte_t pte;
395 int refs; 395 int refs;
396 396
@@ -413,6 +413,7 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
413 head = pte_page(pte); 413 head = pte_page(pte);
414 414
415 page = head + ((addr & (sz-1)) >> PAGE_SHIFT); 415 page = head + ((addr & (sz-1)) >> PAGE_SHIFT);
416 tail = page;
416 do { 417 do {
417 VM_BUG_ON(compound_head(page) != head); 418 VM_BUG_ON(compound_head(page) != head);
418 pages[*nr] = page; 419 pages[*nr] = page;
@@ -428,10 +429,20 @@ static noinline int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long add
428 429
429 if (unlikely(pte_val(pte) != pte_val(*ptep))) { 430 if (unlikely(pte_val(pte) != pte_val(*ptep))) {
430 /* Could be optimized better */ 431 /* Could be optimized better */
431 while (*nr) { 432 *nr -= refs;
432 put_page(page); 433 while (refs--)
433 (*nr)--; 434 put_page(head);
434 } 435 return 0;
436 }
437
438 /*
439 * Any tail page need their mapcount reference taken before we
440 * return.
441 */
442 while (refs--) {
443 if (PageTail(tail))
444 get_huge_page_tail(tail);
445 tail++;
435 } 446 }
436 447
437 return 1; 448 return 1;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index c65f75aa7ff7..22ffccd8bef5 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1608,6 +1608,7 @@ int fsl_rio_setup(struct platform_device *dev)
1608 return 0; 1608 return 0;
1609err: 1609err:
1610 iounmap(priv->regs_win); 1610 iounmap(priv->regs_win);
1611 release_resource(&port->iores);
1611err_res: 1612err_res:
1612 kfree(priv); 1613 kfree(priv);
1613err_priv: 1614err_priv:
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 45b405ca2567..65cb06e2af4e 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -52,7 +52,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
52 unsigned long end, int write, struct page **pages, int *nr) 52 unsigned long end, int write, struct page **pages, int *nr)
53{ 53{
54 unsigned long mask, result; 54 unsigned long mask, result;
55 struct page *head, *page; 55 struct page *head, *page, *tail;
56 int refs; 56 int refs;
57 57
58 result = write ? 0 : _SEGMENT_ENTRY_RO; 58 result = write ? 0 : _SEGMENT_ENTRY_RO;
@@ -64,6 +64,7 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
64 refs = 0; 64 refs = 0;
65 head = pmd_page(pmd); 65 head = pmd_page(pmd);
66 page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT); 66 page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
67 tail = page;
67 do { 68 do {
68 VM_BUG_ON(compound_head(page) != head); 69 VM_BUG_ON(compound_head(page) != head);
69 pages[*nr] = page; 70 pages[*nr] = page;
@@ -81,6 +82,17 @@ static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
81 *nr -= refs; 82 *nr -= refs;
82 while (refs--) 83 while (refs--)
83 put_page(head); 84 put_page(head);
85 return 0;
86 }
87
88 /*
89 * Any tail page need their mapcount reference taken before we
90 * return.
91 */
92 while (refs--) {
93 if (PageTail(tail))
94 get_huge_page_tail(tail);
95 tail++;
84 } 96 }
85 97
86 return 1; 98 return 1;
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index a986b5d05712..42c55df3aec3 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -56,6 +56,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
56 put_page(head); 56 put_page(head);
57 return 0; 57 return 0;
58 } 58 }
59 if (head != page)
60 get_huge_page_tail(page);
59 61
60 pages[*nr] = page; 62 pages[*nr] = page;
61 (*nr)++; 63 (*nr)++;
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index dbe34b931374..ea305856151c 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -108,16 +108,6 @@ static inline void get_head_page_multiple(struct page *page, int nr)
108 SetPageReferenced(page); 108 SetPageReferenced(page);
109} 109}
110 110
111static inline void get_huge_page_tail(struct page *page)
112{
113 /*
114 * __split_huge_page_refcount() cannot run
115 * from under us.
116 */
117 VM_BUG_ON(atomic_read(&page->_count) < 0);
118 atomic_inc(&page->_count);
119}
120
121static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr, 111static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
122 unsigned long end, int write, struct page **pages, int *nr) 112 unsigned long end, int write, struct page **pages, int *nr)
123{ 113{