This commit was manufactured by cvs2svn to create branch
[linux-2.6.git] / include / asm-i386 / checksum.h
index 96e4b2d..04b4d2a 100644 (file)
@@ -25,7 +25,7 @@ asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsign
  * better 64-bit) boundary
  */
 
-asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+asmlinkage unsigned int direct_csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
                                                   int *src_err_ptr, int *dst_err_ptr);
 
 /*
@@ -39,14 +39,19 @@ static __inline__
 unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
                                        int len, int sum)
 {
-       return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+       /*
+        * The direct function is OK for kernel-space => kernel-space copies:
+        */
+       return direct_csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
 }
 
 static __inline__
 unsigned int csum_partial_copy_from_user ( const char __user *src, char *dst,
                                                int len, int sum, int *err_ptr)
 {
-       return csum_partial_copy_generic ( (__force char *)src, dst, len, sum, err_ptr, NULL);
+       if (copy_from_user(dst, src, len))
+               *err_ptr = -EFAULT;
+       return csum_partial(dst, len, sum);
 }
 
 /*
@@ -172,13 +177,28 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  *     Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user(const char *src, 
+static __inline__ unsigned int direct_csum_and_copy_to_user(const char *src, 
                                                     char __user *dst,
                                                     int len, int sum, 
                                                     int *err_ptr)
 {
        if (access_ok(VERIFY_WRITE, dst, len))
-               return csum_partial_copy_generic(src, (__force char *)dst, len, sum, NULL, err_ptr);
+               return direct_csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+       if (len)
+               *err_ptr = -EFAULT;
+
+       return -1; /* invalid checksum */
+}
+
+static __inline__ unsigned int csum_and_copy_to_user(const char *src, char __user *dst,
+                                   int len, int sum, int *err_ptr)
+{
+       if (access_ok(VERIFY_WRITE, dst, len)) {
+               if (copy_to_user(dst, src, len))
+                       *err_ptr = -EFAULT;
+               return csum_partial(src, len, sum);
+       }
 
        if (len)
                *err_ptr = -EFAULT;