Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-drm-fsl-dcu.git] / include / asm-i386 / uaccess.h
index 8462f8e0e658fda0f0cdb630b559ff0098526ef9..70829ae3ad527729cf49e79be5dcd247d1fd9eb5 100644 (file)
@@ -54,10 +54,10 @@ extern struct movsl_mask {
  * This needs 33-bit arithmetic. We have a carry...
  */
 #define __range_ok(addr,size) ({ \
-       unsigned long flag,sum; \
+       unsigned long flag,roksum; \
        __chk_user_ptr(addr); \
        asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
-               :"=&r" (flag), "=r" (sum) \
+               :"=&r" (flag), "=r" (roksum) \
                :"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \
        flag; })
 
@@ -390,8 +390,12 @@ unsigned long __must_check __copy_to_user_ll(void __user *to,
                                const void *from, unsigned long n);
 unsigned long __must_check __copy_from_user_ll(void *to,
                                const void __user *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll_nozero(void *to,
+                               const void __user *from, unsigned long n);
 unsigned long __must_check __copy_from_user_ll_nocache(void *to,
                                const void __user *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,
+                               const void __user *from, unsigned long n);
 
 /*
  * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
@@ -400,6 +404,27 @@ unsigned long __must_check __copy_from_user_ll_nocache(void *to,
  * anything, so this is accurate.
  */
 
+static __always_inline unsigned long __must_check
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+{
+       if (__builtin_constant_p(n)) {
+               unsigned long ret;
+
+               switch (n) {
+               case 1:
+                       __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);
+                       return ret;
+               case 2:
+                       __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);
+                       return ret;
+               case 4:
+                       __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);
+                       return ret;
+               }
+       }
+       return __copy_to_user_ll(to, from, n);
+}
+
 /**
  * __copy_to_user: - Copy a block of data into user space, with less checking.
  * @to:   Destination address, in user space.
@@ -415,31 +440,36 @@ unsigned long __must_check __copy_from_user_ll_nocache(void *to,
  * On success, this will be zero.
  */
 static __always_inline unsigned long __must_check
-__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_to_user_inatomic(to, from, n);
+}
+
+static __always_inline unsigned long
+__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
+       /* Avoid zeroing the tail if the copy fails..
+        * If 'n' is constant and 1, 2, or 4, we do still zero on a failure,
+        * but as the zeroing behaviour is only significant when n is not
+        * constant, that shouldn't be a problem.
+        */
        if (__builtin_constant_p(n)) {
                unsigned long ret;
 
                switch (n) {
                case 1:
-                       __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1);
+                       __get_user_size(*(u8 *)to, from, 1, ret, 1);
                        return ret;
                case 2:
-                       __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2);
+                       __get_user_size(*(u16 *)to, from, 2, ret, 2);
                        return ret;
                case 4:
-                       __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4);
+                       __get_user_size(*(u32 *)to, from, 4, ret, 4);
                        return ret;
                }
        }
-       return __copy_to_user_ll(to, from, n);
-}
-
-static __always_inline unsigned long __must_check
-__copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-       might_sleep();
-       return __copy_to_user_inatomic(to, from, n);
+       return __copy_from_user_ll_nozero(to, from, n);
 }
 
 /**
@@ -458,10 +488,16 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
  *
  * If some data could not be copied, this function will pad the copied
  * data to the requested size using zero bytes.
+ *
+ * An alternate version - __copy_from_user_inatomic() - may be called from
+ * atomic context and will fail rather than sleep.  In this case the
+ * uncopied bytes will *NOT* be padded with zeros.  See fs/filemap.h
+ * for explanation of why this is needed.
  */
 static __always_inline unsigned long
-__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
+__copy_from_user(void *to, const void __user *from, unsigned long n)
 {
+       might_sleep();
        if (__builtin_constant_p(n)) {
                unsigned long ret;
 
@@ -482,9 +518,10 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 #define ARCH_HAS_NOCACHE_UACCESS
 
-static __always_inline unsigned long __copy_from_user_inatomic_nocache(void *to,
+static __always_inline unsigned long __copy_from_user_nocache(void *to,
                                const void __user *from, unsigned long n)
 {
+       might_sleep();
        if (__builtin_constant_p(n)) {
                unsigned long ret;
 
@@ -504,17 +541,9 @@ static __always_inline unsigned long __copy_from_user_inatomic_nocache(void *to,
 }
 
 static __always_inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n)
 {
-       might_sleep();
-       return __copy_from_user_inatomic(to, from, n);
-}
-
-static __always_inline unsigned long
-__copy_from_user_nocache(void *to, const void __user *from, unsigned long n)
-{
-       might_sleep();
-       return __copy_from_user_inatomic_nocache(to, from, n);
+       return __copy_from_user_ll_nocache_nozero(to, from, n);
 }
 
 unsigned long __must_check copy_to_user(void __user *to,