xref: /openbmc/linux/lib/raid6/recov_neon.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
26ec4e251SArd Biesheuvel /*
36ec4e251SArd Biesheuvel  * Copyright (C) 2012 Intel Corporation
46ec4e251SArd Biesheuvel  * Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
56ec4e251SArd Biesheuvel  */
66ec4e251SArd Biesheuvel 
76ec4e251SArd Biesheuvel #include <linux/raid/pq.h>
86ec4e251SArd Biesheuvel 
96ec4e251SArd Biesheuvel #ifdef __KERNEL__
106ec4e251SArd Biesheuvel #include <asm/neon.h>
11*3de13550SArnd Bergmann #include "neon.h"
126ec4e251SArd Biesheuvel #else
136ec4e251SArd Biesheuvel #define kernel_neon_begin()
146ec4e251SArd Biesheuvel #define kernel_neon_end()
156ec4e251SArd Biesheuvel #define cpu_has_neon()		(1)
166ec4e251SArd Biesheuvel #endif
176ec4e251SArd Biesheuvel 
raid6_has_neon(void)186ec4e251SArd Biesheuvel static int raid6_has_neon(void)
196ec4e251SArd Biesheuvel {
206ec4e251SArd Biesheuvel 	return cpu_has_neon();
216ec4e251SArd Biesheuvel }
226ec4e251SArd Biesheuvel 
raid6_2data_recov_neon(int disks,size_t bytes,int faila,int failb,void ** ptrs)236ec4e251SArd Biesheuvel static void raid6_2data_recov_neon(int disks, size_t bytes, int faila,
246ec4e251SArd Biesheuvel 		int failb, void **ptrs)
256ec4e251SArd Biesheuvel {
266ec4e251SArd Biesheuvel 	u8 *p, *q, *dp, *dq;
276ec4e251SArd Biesheuvel 	const u8 *pbmul;	/* P multiplier table for B data */
286ec4e251SArd Biesheuvel 	const u8 *qmul;		/* Q multiplier table (for both) */
296ec4e251SArd Biesheuvel 
306ec4e251SArd Biesheuvel 	p = (u8 *)ptrs[disks - 2];
316ec4e251SArd Biesheuvel 	q = (u8 *)ptrs[disks - 1];
326ec4e251SArd Biesheuvel 
336ec4e251SArd Biesheuvel 	/*
346ec4e251SArd Biesheuvel 	 * Compute syndrome with zero for the missing data pages
356ec4e251SArd Biesheuvel 	 * Use the dead data pages as temporary storage for
366ec4e251SArd Biesheuvel 	 * delta p and delta q
376ec4e251SArd Biesheuvel 	 */
386ec4e251SArd Biesheuvel 	dp = (u8 *)ptrs[faila];
396ec4e251SArd Biesheuvel 	ptrs[faila] = (void *)raid6_empty_zero_page;
406ec4e251SArd Biesheuvel 	ptrs[disks - 2] = dp;
416ec4e251SArd Biesheuvel 	dq = (u8 *)ptrs[failb];
426ec4e251SArd Biesheuvel 	ptrs[failb] = (void *)raid6_empty_zero_page;
436ec4e251SArd Biesheuvel 	ptrs[disks - 1] = dq;
446ec4e251SArd Biesheuvel 
456ec4e251SArd Biesheuvel 	raid6_call.gen_syndrome(disks, bytes, ptrs);
466ec4e251SArd Biesheuvel 
476ec4e251SArd Biesheuvel 	/* Restore pointer table */
486ec4e251SArd Biesheuvel 	ptrs[faila]     = dp;
496ec4e251SArd Biesheuvel 	ptrs[failb]     = dq;
506ec4e251SArd Biesheuvel 	ptrs[disks - 2] = p;
516ec4e251SArd Biesheuvel 	ptrs[disks - 1] = q;
526ec4e251SArd Biesheuvel 
536ec4e251SArd Biesheuvel 	/* Now, pick the proper data tables */
546ec4e251SArd Biesheuvel 	pbmul = raid6_vgfmul[raid6_gfexi[failb-faila]];
556ec4e251SArd Biesheuvel 	qmul  = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
566ec4e251SArd Biesheuvel 					 raid6_gfexp[failb]]];
576ec4e251SArd Biesheuvel 
586ec4e251SArd Biesheuvel 	kernel_neon_begin();
596ec4e251SArd Biesheuvel 	__raid6_2data_recov_neon(bytes, p, q, dp, dq, pbmul, qmul);
606ec4e251SArd Biesheuvel 	kernel_neon_end();
616ec4e251SArd Biesheuvel }
626ec4e251SArd Biesheuvel 
raid6_datap_recov_neon(int disks,size_t bytes,int faila,void ** ptrs)636ec4e251SArd Biesheuvel static void raid6_datap_recov_neon(int disks, size_t bytes, int faila,
646ec4e251SArd Biesheuvel 		void **ptrs)
656ec4e251SArd Biesheuvel {
666ec4e251SArd Biesheuvel 	u8 *p, *q, *dq;
676ec4e251SArd Biesheuvel 	const u8 *qmul;		/* Q multiplier table */
686ec4e251SArd Biesheuvel 
696ec4e251SArd Biesheuvel 	p = (u8 *)ptrs[disks - 2];
706ec4e251SArd Biesheuvel 	q = (u8 *)ptrs[disks - 1];
716ec4e251SArd Biesheuvel 
726ec4e251SArd Biesheuvel 	/*
736ec4e251SArd Biesheuvel 	 * Compute syndrome with zero for the missing data page
746ec4e251SArd Biesheuvel 	 * Use the dead data page as temporary storage for delta q
756ec4e251SArd Biesheuvel 	 */
766ec4e251SArd Biesheuvel 	dq = (u8 *)ptrs[faila];
776ec4e251SArd Biesheuvel 	ptrs[faila] = (void *)raid6_empty_zero_page;
786ec4e251SArd Biesheuvel 	ptrs[disks - 1] = dq;
796ec4e251SArd Biesheuvel 
806ec4e251SArd Biesheuvel 	raid6_call.gen_syndrome(disks, bytes, ptrs);
816ec4e251SArd Biesheuvel 
826ec4e251SArd Biesheuvel 	/* Restore pointer table */
836ec4e251SArd Biesheuvel 	ptrs[faila]     = dq;
846ec4e251SArd Biesheuvel 	ptrs[disks - 1] = q;
856ec4e251SArd Biesheuvel 
866ec4e251SArd Biesheuvel 	/* Now, pick the proper data tables */
876ec4e251SArd Biesheuvel 	qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
886ec4e251SArd Biesheuvel 
896ec4e251SArd Biesheuvel 	kernel_neon_begin();
906ec4e251SArd Biesheuvel 	__raid6_datap_recov_neon(bytes, p, q, dq, qmul);
916ec4e251SArd Biesheuvel 	kernel_neon_end();
926ec4e251SArd Biesheuvel }
936ec4e251SArd Biesheuvel 
946ec4e251SArd Biesheuvel const struct raid6_recov_calls raid6_recov_neon = {
956ec4e251SArd Biesheuvel 	.data2		= raid6_2data_recov_neon,
966ec4e251SArd Biesheuvel 	.datap		= raid6_datap_recov_neon,
976ec4e251SArd Biesheuvel 	.valid		= raid6_has_neon,
986ec4e251SArd Biesheuvel 	.name		= "neon",
996ec4e251SArd Biesheuvel 	.priority	= 10,
1006ec4e251SArd Biesheuvel };
101