xref: /linux/lib/raid/raid6/arm/recov_neon.c (revision adfcf6e89bc1322c4a6cc37ad32e411cf0500622)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2012 Intel Corporation
4  * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
5  */
6 
7 #include <linux/mm.h>
8 #include <linux/raid/pq.h>
9 #include <asm/simd.h>
10 #include "algos.h"
11 #include "arm/neon.h"
12 
13 static void raid6_2data_recov_neon(int disks, size_t bytes, int faila,
14 		int failb, void **ptrs)
15 {
16 	u8 *p, *q, *dp, *dq;
17 	const u8 *pbmul;	/* P multiplier table for B data */
18 	const u8 *qmul;		/* Q multiplier table (for both) */
19 
20 	p = (u8 *)ptrs[disks - 2];
21 	q = (u8 *)ptrs[disks - 1];
22 
23 	/*
24 	 * Compute syndrome with zero for the missing data pages
25 	 * Use the dead data pages as temporary storage for
26 	 * delta p and delta q
27 	 */
28 	dp = (u8 *)ptrs[faila];
29 	ptrs[faila] = page_address(ZERO_PAGE(0));
30 	ptrs[disks - 2] = dp;
31 	dq = (u8 *)ptrs[failb];
32 	ptrs[failb] = page_address(ZERO_PAGE(0));
33 	ptrs[disks - 1] = dq;
34 
35 	raid6_gen_syndrome(disks, bytes, ptrs);
36 
37 	/* Restore pointer table */
38 	ptrs[faila]     = dp;
39 	ptrs[failb]     = dq;
40 	ptrs[disks - 2] = p;
41 	ptrs[disks - 1] = q;
42 
43 	/* Now, pick the proper data tables */
44 	pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
45 	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
46 					 raid6_gfexp[failb]]];
47 
48 	scoped_ksimd()
49 		__raid6_2data_recov_neon(bytes, p, q, dp, dq, pbmul, qmul);
50 }
51 
52 static void raid6_datap_recov_neon(int disks, size_t bytes, int faila,
53 		void **ptrs)
54 {
55 	u8 *p, *q, *dq;
56 	const u8 *qmul;		/* Q multiplier table */
57 
58 	p = (u8 *)ptrs[disks - 2];
59 	q = (u8 *)ptrs[disks - 1];
60 
61 	/*
62 	 * Compute syndrome with zero for the missing data page
63 	 * Use the dead data page as temporary storage for delta q
64 	 */
65 	dq = (u8 *)ptrs[faila];
66 	ptrs[faila] = page_address(ZERO_PAGE(0));
67 	ptrs[disks - 1] = dq;
68 
69 	raid6_gen_syndrome(disks, bytes, ptrs);
70 
71 	/* Restore pointer table */
72 	ptrs[faila]     = dq;
73 	ptrs[disks - 1] = q;
74 
75 	/* Now, pick the proper data tables */
76 	qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
77 
78 	scoped_ksimd()
79 		__raid6_datap_recov_neon(bytes, p, q, dq, qmul);
80 }
81 
82 const struct raid6_recov_calls raid6_recov_neon = {
83 	.data2		= raid6_2data_recov_neon,
84 	.datap		= raid6_datap_recov_neon,
85 	.name		= "neon",
86 };
87