Commit | Line | Data |
---|---|---|
b886d83c | 1 | // SPDX-License-Identifier: GPL-2.0-only |
6ec4e251 AB |
2 | /* |
3 | * Copyright (C) 2012 Intel Corporation | |
4 | * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org> | |
6ec4e251 AB |
5 | */ |
6 | ||
7 | #include <linux/raid/pq.h> | |
8 | ||
9 | #ifdef __KERNEL__ | |
10 | #include <asm/neon.h> | |
11 | #else | |
12 | #define kernel_neon_begin() | |
13 | #define kernel_neon_end() | |
14 | #define cpu_has_neon() (1) | |
15 | #endif | |
16 | ||
17 | static int raid6_has_neon(void) | |
18 | { | |
19 | return cpu_has_neon(); | |
20 | } | |
21 | ||
22 | void __raid6_2data_recov_neon(int bytes, uint8_t *p, uint8_t *q, uint8_t *dp, | |
23 | uint8_t *dq, const uint8_t *pbmul, | |
24 | const uint8_t *qmul); | |
25 | ||
26 | void __raid6_datap_recov_neon(int bytes, uint8_t *p, uint8_t *q, uint8_t *dq, | |
27 | const uint8_t *qmul); | |
28 | ||
29 | static void raid6_2data_recov_neon(int disks, size_t bytes, int faila, | |
30 | int failb, void **ptrs) | |
31 | { | |
32 | u8 *p, *q, *dp, *dq; | |
33 | const u8 *pbmul; /* P multiplier table for B data */ | |
34 | const u8 *qmul; /* Q multiplier table (for both) */ | |
35 | ||
36 | p = (u8 *)ptrs[disks - 2]; | |
37 | q = (u8 *)ptrs[disks - 1]; | |
38 | ||
39 | /* | |
40 | * Compute syndrome with zero for the missing data pages | |
41 | * Use the dead data pages as temporary storage for | |
42 | * delta p and delta q | |
43 | */ | |
44 | dp = (u8 *)ptrs[faila]; | |
45 | ptrs[faila] = (void *)raid6_empty_zero_page; | |
46 | ptrs[disks - 2] = dp; | |
47 | dq = (u8 *)ptrs[failb]; | |
48 | ptrs[failb] = (void *)raid6_empty_zero_page; | |
49 | ptrs[disks - 1] = dq; | |
50 | ||
51 | raid6_call.gen_syndrome(disks, bytes, ptrs); | |
52 | ||
53 | /* Restore pointer table */ | |
54 | ptrs[faila] = dp; | |
55 | ptrs[failb] = dq; | |
56 | ptrs[disks - 2] = p; | |
57 | ptrs[disks - 1] = q; | |
58 | ||
59 | /* Now, pick the proper data tables */ | |
60 | pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]]; | |
61 | qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^ | |
62 | raid6_gfexp[failb]]]; | |
63 | ||
64 | kernel_neon_begin(); | |
65 | __raid6_2data_recov_neon(bytes, p, q, dp, dq, pbmul, qmul); | |
66 | kernel_neon_end(); | |
67 | } | |
68 | ||
69 | static void raid6_datap_recov_neon(int disks, size_t bytes, int faila, | |
70 | void **ptrs) | |
71 | { | |
72 | u8 *p, *q, *dq; | |
73 | const u8 *qmul; /* Q multiplier table */ | |
74 | ||
75 | p = (u8 *)ptrs[disks - 2]; | |
76 | q = (u8 *)ptrs[disks - 1]; | |
77 | ||
78 | /* | |
79 | * Compute syndrome with zero for the missing data page | |
80 | * Use the dead data page as temporary storage for delta q | |
81 | */ | |
82 | dq = (u8 *)ptrs[faila]; | |
83 | ptrs[faila] = (void *)raid6_empty_zero_page; | |
84 | ptrs[disks - 1] = dq; | |
85 | ||
86 | raid6_call.gen_syndrome(disks, bytes, ptrs); | |
87 | ||
88 | /* Restore pointer table */ | |
89 | ptrs[faila] = dq; | |
90 | ptrs[disks - 1] = q; | |
91 | ||
92 | /* Now, pick the proper data tables */ | |
93 | qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]]; | |
94 | ||
95 | kernel_neon_begin(); | |
96 | __raid6_datap_recov_neon(bytes, p, q, dq, qmul); | |
97 | kernel_neon_end(); | |
98 | } | |
99 | ||
100 | const struct raid6_recov_calls raid6_recov_neon = { | |
101 | .data2 = raid6_2data_recov_neon, | |
102 | .datap = raid6_datap_recov_neon, | |
103 | .valid = raid6_has_neon, | |
104 | .name = "neon", | |
105 | .priority = 10, | |
106 | }; |