OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [x86_64/] [lib/] [csum-wrappers.c] - Blame information for rev 1781

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* Copyright 2002,2003 Andi Kleen, SuSE Labs.
2
 * Subject to the GNU Public License v.2
3
 *
4
 * Wrappers of assembly checksum functions for x86-64.
5
 */
6
 
7
#include <asm/checksum.h>
8
#include <linux/module.h>
9
 
10
/**
11
 * csum_partial_copy_from_user - Copy and checksum from user space.
12
 * @src: source address (user space)
13
 * @dst: destination address
14
 * @len: number of bytes to be copied.
15
 * @isum: initial sum that is added into the result (32bit unfolded)
16
 * @errp: set to -EFAULT for an bad source address.
17
 *
18
 * Returns an 32bit unfolded checksum of the buffer.
19
 * src and dst are best aligned to 64bits.
20
 */
21
unsigned int
22
csum_partial_copy_from_user(const char *src, char *dst,
23
                            int len, unsigned int isum, int *errp)
24
{
25
        *errp = 0;
26
        if (likely(access_ok(VERIFY_READ,src, len))) {
27
                /* Why 6, not 7? To handle odd addresses aligned we
28
                   would need to do considerable complications to fix the
29
                   checksum which is defined as an 16bit accumulator. The
30
                   fix alignment code is primarily for performance
31
                   compatibility with 32bit and that will handle odd
32
                   addresses slowly too. */
33
                if (unlikely((unsigned long)src & 6)) {
34
                        while (((unsigned long)src & 6) && len >= 2) {
35
                                __u16 val16;
36
                                *errp = __get_user(val16, (__u16 *)src);
37
                                if (*errp)
38
                                        return isum;
39
                                *(__u16 *)dst = val16;
40
                                isum = add32_with_carry(isum, val16);
41
                                src += 2;
42
                                dst += 2;
43
                                len -= 2;
44
                        }
45
                }
46
                isum = csum_partial_copy_generic(src,dst,len,isum,errp,NULL);
47
                if (likely(*errp == 0))
48
                        return isum;
49
        }
50
        *errp = -EFAULT;
51
        memset(dst,0,len);
52
        return isum;
53
}
54
 
55
EXPORT_SYMBOL(csum_partial_copy_from_user);
56
 
57
/**
58
 * csum_partial_copy_to_user - Copy and checksum to user space.
59
 * @src: source address
60
 * @dst: destination address (user space)
61
 * @len: number of bytes to be copied.
62
 * @isum: initial sum that is added into the result (32bit unfolded)
63
 * @errp: set to -EFAULT for an bad destination address.
64
 *
65
 * Returns an 32bit unfolded checksum of the buffer.
66
 * src and dst are best aligned to 64bits.
67
 */
68
unsigned int
69
csum_partial_copy_to_user(const char *src, char *dst,
70
                          int len, unsigned int isum, int *errp)
71
{
72
        if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
73
                *errp = -EFAULT;
74
                return 0;
75
        }
76
 
77
        if (unlikely((unsigned long)dst & 6)) {
78
                while (((unsigned long)dst & 6) && len >= 2) {
79
                        __u16 val16 = *(__u16 *)src;
80
                        isum = add32_with_carry(isum, val16);
81
                        *errp = __put_user(val16, (__u16 *)dst);
82
                        if (*errp)
83
                                return isum;
84
                        src += 2;
85
                        dst += 2;
86
                        len -= 2;
87
                }
88
        }
89
 
90
        *errp = 0;
91
        return csum_partial_copy_generic(src,dst,len,isum,NULL,errp);
92
}
93
 
94
EXPORT_SYMBOL(csum_partial_copy_to_user);
95
 
96
/**
97
 * csum_partial_copy_nocheck - Copy and checksum.
98
 * @src: source address
99
 * @dst: destination address
100
 * @len: number of bytes to be copied.
101
 * @isum: initial sum that is added into the result (32bit unfolded)
102
 *
103
 * Returns an 32bit unfolded checksum of the buffer.
104
 */
105
unsigned int
106
csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
107
{
108
        return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL);
109
}
110
 
111
unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
112
                               __u32 len, unsigned short proto, unsigned int sum)
113
{
114
        __u64 rest, sum64;
115
 
116
        rest = (__u64)htonl(len) + (__u64)htons(proto) + (__u64)sum;
117
        asm("  addq (%[saddr]),%[sum]\n"
118
            "  adcq 8(%[saddr]),%[sum]\n"
119
            "  adcq (%[daddr]),%[sum]\n"
120
            "  adcq 8(%[daddr]),%[sum]\n"
121
            "  adcq $0,%[sum]\n"
122
            : [sum] "=r" (sum64)
123
            : "[sum]" (rest),[saddr] "r" (saddr), [daddr] "r" (daddr));
124
        return csum_fold(add32_with_carry(sum64 & 0xffffffff, sum64>>32));
125
}
126
 
127
EXPORT_SYMBOL(csum_ipv6_magic);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.