Merge git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for...
[pandora-kernel.git] / arch / x86 / lib / usercopy.c
1 /*
2  * User address space access functions.
3  *
4  *  For licencing details see kernel-base/COPYING
5  */
6
7 #include <linux/highmem.h>
8 #include <linux/module.h>
9
10 /*
11  * best effort, GUP based copy_from_user() that is NMI-safe
12  */
13 unsigned long
14 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
15 {
16         unsigned long offset, addr = (unsigned long)from;
17         unsigned long size, len = 0;
18         struct page *page;
19         void *map;
20         int ret;
21
22         do {
23                 ret = __get_user_pages_fast(addr, 1, 0, &page);
24                 if (!ret)
25                         break;
26
27                 offset = addr & (PAGE_SIZE - 1);
28                 size = min(PAGE_SIZE - offset, n - len);
29
30                 map = kmap_atomic(page);
31                 memcpy(to, map+offset, size);
32                 kunmap_atomic(map);
33                 put_page(page);
34
35                 len  += size;
36                 to   += size;
37                 addr += size;
38
39         } while (len < n);
40
41         return len;
42 }
43 EXPORT_SYMBOL_GPL(copy_from_user_nmi);