diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-24 12:45:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-24 12:45:47 -0700 |
commit | 83da00fbc0c57ce6f84455156a2e3cc057fe7344 (patch) | |
tree | fac652b63aac0bfade55cd8113afe668f00c9cd8 /arch/sparc/mm | |
parent | 96971e9aa9578322648b2de593fd4863f3d9fc39 (diff) | |
parent | 06090e8ed89ea2113a236befb41f71d51f100e60 (diff) | |
download | talos-op-linux-83da00fbc0c57ce6f84455156a2e3cc057fe7344.tar.gz talos-op-linux-83da00fbc0c57ce6f84455156a2e3cc057fe7344.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull two sparc fixes from David Miller:
1) Fix boots with gcc-4.9 compiled sparc64 kernels.
2) Add missing __get_user_pages_fast() on sparc64 to fix hangs on
futexes used in transparent hugepage areas.
It's really idiotic to have a weak symbolled fallback that just
returns zero, and causes this kind of bug. There should be no
backup implementation and the link should fail if the architecture
fails to provide __get_user_pages_fast() and supports transparent
hugepages.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
sparc64: Implement __get_user_pages_fast().
sparc64: Fix register corruption in top-most kernel stack frame during boot.
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r-- | arch/sparc/mm/gup.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c index 1aed0432c64b..ae6ce383d4df 100644 --- a/arch/sparc/mm/gup.c +++ b/arch/sparc/mm/gup.c @@ -160,6 +160,36 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, return 1; } +int __get_user_pages_fast(unsigned long start, int nr_pages, int write, + struct page **pages) +{ + struct mm_struct *mm = current->mm; + unsigned long addr, len, end; + unsigned long next, flags; + pgd_t *pgdp; + int nr = 0; + + start &= PAGE_MASK; + addr = start; + len = (unsigned long) nr_pages << PAGE_SHIFT; + end = start + len; + + local_irq_save(flags); + pgdp = pgd_offset(mm, addr); + do { + pgd_t pgd = *pgdp; + + next = pgd_addr_end(addr, end); + if (pgd_none(pgd)) + break; + if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) + break; + } while (pgdp++, addr = next, addr != end); + local_irq_restore(flags); + + return nr; +} + int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages) { |