This source file includes following definitions.
- from64to16
- do_csum_c
- csum_partial_copy_from_user
- csum_partial_copy_nocheck
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/module.h>
  12 #include <linux/types.h>
  13 #include <linux/string.h>
  14 
  15 #include <linux/uaccess.h>
  16 
  17 
  18 
  19 
  20 static inline unsigned
  21 short from64to16(unsigned long x)
  22 {
  23         
  24         x = (x & 0xffffffff) + (x >> 32);
  25         
  26         x = (x & 0xffff) + (x >> 16);
  27         
  28         x = (x & 0xffff) + (x >> 16);
  29         
  30         x = (x & 0xffff) + (x >> 16);
  31         return x;
  32 }
  33 
  34 static inline
  35 unsigned long do_csum_c(const unsigned char * buff, int len, unsigned int psum)
  36 {
  37         int odd, count;
  38         unsigned long result = (unsigned long)psum;
  39 
  40         if (len <= 0)
  41                 goto out;
  42         odd = 1 & (unsigned long) buff;
  43         if (odd) {
  44                 result = *buff << 8;
  45                 len--;
  46                 buff++;
  47         }
  48         count = len >> 1;               
  49         if (count) {
  50                 if (2 & (unsigned long) buff) {
  51                         result += *(unsigned short *) buff;
  52                         count--;
  53                         len -= 2;
  54                         buff += 2;
  55                 }
  56                 count >>= 1;            
  57                 if (count) {
  58                         if (4 & (unsigned long) buff) {
  59                                 result += *(unsigned int *) buff;
  60                                 count--;
  61                                 len -= 4;
  62                                 buff += 4;
  63                         }
  64                         count >>= 1;    
  65                         if (count) {
  66                                 unsigned long carry = 0;
  67                                 do {
  68                                         unsigned long w = *(unsigned long *) buff;
  69                                         count--;
  70                                         buff += 8;
  71                                         result += carry;
  72                                         result += w;
  73                                         carry = (w > result);
  74                                 } while (count);
  75                                 result += carry;
  76                                 result = (result & 0xffffffff) + (result >> 32);
  77                         }
  78                         if (len & 4) {
  79                                 result += *(unsigned int *) buff;
  80                                 buff += 4;
  81                         }
  82                 }
  83                 if (len & 2) {
  84                         result += *(unsigned short *) buff;
  85                         buff += 2;
  86                 }
  87         }
  88         if (len & 1)
  89                 result += *buff;
  90 
  91         result = from64to16(result);
  92 
  93         if (odd)
  94                 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
  95 
  96 out:
  97         return result;
  98 }
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 extern unsigned long do_csum(const unsigned char *, long);
 107 
 108 __wsum
 109 csum_partial_copy_from_user(const void __user *src, void *dst,
 110                                 int len, __wsum psum, int *errp)
 111 {
 112         unsigned long result;
 113 
 114         
 115 
 116 
 117 
 118 
 119 
 120         if (__copy_from_user(dst, src, len) != 0 && errp)
 121                 *errp = -EFAULT;
 122 
 123         result = do_csum(dst, len);
 124 
 125         
 126         result += (__force u32)psum;
 127         
 128         result = (result & 0xffffffff) + (result >> 32);
 129         return (__force __wsum)result;
 130 }
 131 
 132 EXPORT_SYMBOL(csum_partial_copy_from_user);
 133 
 134 __wsum
 135 csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
 136 {
 137         return csum_partial_copy_from_user((__force const void __user *)src,
 138                                            dst, len, sum, NULL);
 139 }
 140 
 141 EXPORT_SYMBOL(csum_partial_copy_nocheck);