diff --git a/src/arch/s390x/include/bits/tcpip.h b/src/arch/s390x/include/bits/tcpip.h new file mode 100644 index 000000000..423b1a176 --- /dev/null +++ b/src/arch/s390x/include/bits/tcpip.h @@ -0,0 +1,41 @@ +#ifndef _BITS_TCPIP_H +#define _BITS_TCPIP_H + +/** @file + * + * Transport-network layer interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** + * Calculate continued TCP/IP checkum + * + * @v partial Checksum of already-summed data, in network byte order + * @v data Data buffer + * @v len Length of data buffer + * @ret cksum Updated checksum, in network byte order + */ +static inline __attribute__ (( always_inline )) uint16_t +tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) { + struct s390x_pointer_pair pair = { data, len }; + unsigned int cksum; + + __asm__ ( /* Calculate 32-bit checksum */ + "\n1:\n\t" + "cksm %0, %1\n\t" + "jo 1b\n\t" + /* Fold down to 16 bits */ + "risbgz %1, %0, 32, 47, 16\n\t" + "alr %0, %1\n\t" + "srl %0, 16\n\t" + "alcr %0, %N1\n\t" + : "=&r" ( cksum ), + "+r" ( pair ) + : "0" ( ~partial ) ); + + return ~cksum; +} + +#endif /* _BITS_TCPIP_H */