Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * This is based on the hostboot ecc code
4 : : *
5 : : * Copyright 2013-2018 IBM Corp.
6 : : */
7 : :
8 : : #ifndef __ECC_H
9 : : #define __ECC_H
10 : :
11 : : #include <stdint.h>
12 : : #include <ccan/endian/endian.h>
13 : :
14 : : struct ecc64 {
15 : : beint64_t data;
16 : : uint8_t ecc;
17 : : } __attribute__((__packed__));
18 : :
19 : : extern int memcpy_from_ecc(beint64_t *dst, struct ecc64 *src, uint64_t len);
20 : : extern int memcpy_from_ecc_unaligned(beint64_t *dst, struct ecc64 *src, uint64_t len,
21 : : uint8_t alignment);
22 : :
23 : : extern int memcpy_to_ecc(struct ecc64 *dst, const beint64_t *src, uint64_t len);
24 : : extern int memcpy_to_ecc_unaligned(struct ecc64 *dst, const beint64_t *src, uint64_t len,
25 : : uint8_t alignment);
26 : :
27 : : /*
28 : : * Calculate the size of a buffer if ECC is added
29 : : *
30 : : * We add 1 byte of ecc for every 8 bytes of data. So we need to round up to 8
31 : : * bytes length and then add 1/8
32 : : */
33 : : #ifndef ALIGN_UP
34 : : #define ALIGN_UP(_v, _a) (((_v) + (_a) - 1) & ~((_a) - 1))
35 : : #endif
36 : :
37 : : #define BYTES_PER_ECC 8
38 : :
39 : 20 : static inline uint64_t ecc_size(uint64_t len)
40 : : {
41 : 20 : return ALIGN_UP(len, BYTES_PER_ECC) >> 3;
42 : : }
43 : :
44 : 20 : static inline uint64_t ecc_buffer_size(uint64_t len)
45 : : {
46 : 20 : return ALIGN_UP(len, BYTES_PER_ECC) + ecc_size(len);
47 : : }
48 : :
49 : : static inline int ecc_buffer_size_check(uint64_t len)
50 : : {
51 : : return len % (BYTES_PER_ECC + 1);
52 : : }
53 : :
54 : 40 : static inline uint64_t ecc_buffer_size_minus_ecc(uint64_t len)
55 : : {
56 : 40 : return len * BYTES_PER_ECC / (BYTES_PER_ECC + 1);
57 : : }
58 : :
59 : 20 : static inline uint64_t ecc_buffer_align(uint64_t start, uint64_t pos)
60 : : {
61 : 20 : return pos - ((pos - start) % (BYTES_PER_ECC + 1));
62 : : }
63 : :
64 : : #endif
|