LCOV - code coverage report
Current view: top level - arch/arm/include/asm - checksum.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 10 70.0 %
Date: 2014-04-16 Functions: 0 0 -
Branches: 3 59 5.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  arch/arm/include/asm/checksum.h
       3                 :            :  *
       4                 :            :  * IP checksum routines
       5                 :            :  *
       6                 :            :  * Copyright (C) Original authors of ../asm-i386/checksum.h
       7                 :            :  * Copyright (C) 1996-1999 Russell King
       8                 :            :  */
       9                 :            : #ifndef __ASM_ARM_CHECKSUM_H
      10                 :            : #define __ASM_ARM_CHECKSUM_H
      11                 :            : 
      12                 :            : #include <linux/in6.h>
      13                 :            : 
      14                 :            : /*
      15                 :            :  * computes the checksum of a memory block at buff, length len,
      16                 :            :  * and adds in "sum" (32-bit)
      17                 :            :  *
      18                 :            :  * returns a 32-bit number suitable for feeding into itself
      19                 :            :  * or csum_tcpudp_magic
      20                 :            :  *
      21                 :            :  * this function must be called with even lengths, except
      22                 :            :  * for the last fragment, which may be odd
      23                 :            :  *
      24                 :            :  * it's best to have buff aligned on a 32-bit boundary
      25                 :            :  */
      26                 :            : __wsum csum_partial(const void *buff, int len, __wsum sum);
      27                 :            : 
      28                 :            : /*
      29                 :            :  * the same as csum_partial, but copies from src while it
      30                 :            :  * checksums, and handles user-space pointer exceptions correctly, when needed.
      31                 :            :  *
      32                 :            :  * here even more important to align src and dst on a 32-bit (or even
      33                 :            :  * better 64-bit) boundary
      34                 :            :  */
      35                 :            : 
      36                 :            : __wsum
      37                 :            : csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
      38                 :            : 
      39                 :            : __wsum
      40                 :            : csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
      41                 :            : 
      42                 :            : /*
      43                 :            :  *      Fold a partial checksum without adding pseudo headers
      44                 :            :  */
      45                 :            : static inline __sum16 csum_fold(__wsum sum)
      46                 :            : {
      47                 :      90328 :         __asm__(
      48                 :            :         "add       %0, %1, %1, ror #16     @ csum_fold"
      49                 :            :         : "=r" (sum)
      50                 :            :         : "r" (sum)
      51                 :            :         : "cc");
      52                 :      90328 :         return (__force __sum16)(~(__force u32)sum >> 16);
      53                 :            : }
      54                 :            : 
      55                 :            : /*
      56                 :            :  *      This is a version of ip_compute_csum() optimized for IP headers,
      57                 :            :  *      which always checksum on 4 octet boundaries.
      58                 :            :  */
      59                 :            : static inline __sum16
      60                 :            : ip_fast_csum(const void *iph, unsigned int ihl)
      61                 :            : {
      62                 :            :         unsigned int tmp1;
      63                 :            :         __wsum sum;
      64                 :            : 
      65                 :      45529 :         __asm__ __volatile__(
      66                 :            :         "ldr       %0, [%1], #4            @ ip_fast_csum          \n\
      67                 :            :         ldr     %3, [%1], #4                                    \n\
      68                 :            :         sub     %2, %2, #5                                      \n\
      69                 :            :         adds    %0, %0, %3                                      \n\
      70                 :            :         ldr     %3, [%1], #4                                    \n\
      71                 :            :         adcs    %0, %0, %3                                      \n\
      72                 :            :         ldr     %3, [%1], #4                                    \n\
      73                 :            : 1:      adcs    %0, %0, %3                                      \n\
      74                 :            :         ldr     %3, [%1], #4                                    \n\
      75                 :            :         tst     %2, #15                 @ do this carefully     \n\
      76                 :            :         subne   %2, %2, #1              @ without destroying    \n\
      77                 :            :         bne     1b                      @ the carry flag        \n\
      78                 :            :         adcs    %0, %0, %3                                      \n\
      79                 :            :         adc     %0, %0, #0"
      80                 :            :         : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
      81                 :            :         : "1" (iph), "2" (ihl)
      82                 :            :         : "cc", "memory");
      83                 :            :         return csum_fold(sum);
      84                 :            : }
      85                 :            : 
      86                 :            : static inline __wsum
      87                 :            : csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
      88                 :            :                    unsigned short proto, __wsum sum)
      89                 :            : {
      90                 :      47487 :         u32 lenprot = len | proto << 16;
      91         [ #  # ]:      46504 :         if (__builtin_constant_p(sum) && sum == 0) {
           [ #  #  -  + ]
           [ #  #  -  + ]
           [ #  #  #  # ]
                 [ #  # ]
      92                 :          0 :                 __asm__(
      93                 :            :                 "adds      %0, %1, %2      @ csum_tcpudp_nofold0   \n\t"
      94                 :            : #ifdef __ARMEB__
      95                 :            :                 "adcs      %0, %0, %3                              \n\t"
      96                 :            : #else
      97                 :            :                 "adcs      %0, %0, %3, ror #8                      \n\t"
      98                 :            : #endif
      99                 :            :                 "adc       %0, %0, #0"
     100                 :            :                 : "=&r" (sum)
     101                 :            :                 : "r" (daddr), "r" (saddr), "r" (lenprot)
     102                 :            :                 : "cc");
     103                 :            :         } else {
     104                 :      22849 :                 __asm__(
     105                 :            :                 "adds      %0, %1, %2      @ csum_tcpudp_nofold    \n\t"
     106                 :            :                 "adcs      %0, %0, %3                              \n\t"
     107                 :            : #ifdef __ARMEB__
     108                 :            :                 "adcs      %0, %0, %4                              \n\t"
     109                 :            : #else
     110                 :            :                 "adcs      %0, %0, %4, ror #8                      \n\t"
     111                 :            : #endif
     112                 :            :                 "adc       %0, %0, #0"
     113                 :            :                 : "=&r"(sum)
     114                 :            :                 : "r" (sum), "r" (daddr), "r" (saddr), "r" (lenprot)
     115                 :            :                 : "cc");
     116                 :            :         }
     117                 :            :         return sum;
     118                 :            : }       
     119                 :            : /*
     120                 :            :  * computes the checksum of the TCP/UDP pseudo-header
     121                 :            :  * returns a 16-bit checksum, already complemented
     122                 :            :  */
     123                 :            : static inline __sum16
     124                 :            : csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
     125                 :            :                   unsigned short proto, __wsum sum)
     126                 :            : {
     127                 :            :         return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
     128                 :            : }
     129                 :            : 
     130                 :            : 
     131                 :            : /*
     132                 :            :  * this routine is used for miscellaneous IP-like checksums, mainly
     133                 :            :  * in icmp.c
     134                 :            :  */
     135                 :            : static inline __sum16
     136                 :            : ip_compute_csum(const void *buff, int len)
     137                 :            : {
     138                 :          0 :         return csum_fold(csum_partial(buff, len, 0));
     139                 :            : }
     140                 :            : 
     141                 :            : #define _HAVE_ARCH_IPV6_CSUM
     142                 :            : extern __wsum
     143                 :            : __csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __be32 len,
     144                 :            :                 __be32 proto, __wsum sum);
     145                 :            : 
     146                 :            : static inline __sum16
     147                 :            : csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len,
     148                 :            :                 unsigned short proto, __wsum sum)
     149                 :            : {
     150 [ #  # ][ -  + ]:         10 :         return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
            [ # ][ #  # ]
         [ #  # ][ #  # ]
            [ #  # ][ # ]
               [ # ][ # ]
            [ #  # ][ # ]
     151                 :          0 :                                            htonl(proto), sum));
     152                 :            : }
     153                 :            : #endif

Generated by: LCOV version 1.9