xref: /linux/lib/raid/raid6/loongarch/loongarch_simd.c (revision 2e05544060b9fef5d4d0e0172944e6956c55080f)
13626738bSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-or-later
23626738bSChristoph Hellwig /*
33626738bSChristoph Hellwig  * RAID6 syndrome calculations in LoongArch SIMD (LSX & LASX)
43626738bSChristoph Hellwig  *
53626738bSChristoph Hellwig  * Copyright 2023 WANG Xuerui <git@xen0n.name>
63626738bSChristoph Hellwig  *
73626738bSChristoph Hellwig  * Based on the generic RAID-6 code (int.uc):
83626738bSChristoph Hellwig  *
93626738bSChristoph Hellwig  * Copyright 2002-2004 H. Peter Anvin
103626738bSChristoph Hellwig  */
113626738bSChristoph Hellwig 
123626738bSChristoph Hellwig #include <asm/cpu-features.h>
133626738bSChristoph Hellwig #include <asm/fpu.h>
14*769d603fSChristoph Hellwig #include "algos.h"
153626738bSChristoph Hellwig 
163626738bSChristoph Hellwig /*
173626738bSChristoph Hellwig  * The vector algorithms are currently priority 0, which means the generic
183626738bSChristoph Hellwig  * scalar algorithms are not being disabled if vector support is present.
193626738bSChristoph Hellwig  * This is like the similar LoongArch RAID5 XOR code, with the main reason
203626738bSChristoph Hellwig  * repeated here: it cannot be ruled out at this point of time, that some
213626738bSChristoph Hellwig  * future (maybe reduced) models could run the vector algorithms slower than
223626738bSChristoph Hellwig  * the scalar ones, maybe for errata or micro-op reasons. It may be
233626738bSChristoph Hellwig  * appropriate to revisit this after one or two more uarch generations.
243626738bSChristoph Hellwig  */
253626738bSChristoph Hellwig 
263626738bSChristoph Hellwig #ifdef CONFIG_CPU_HAS_LSX
273626738bSChristoph Hellwig #define NSIZE 16
283626738bSChristoph Hellwig 
293626738bSChristoph Hellwig static void raid6_lsx_gen_syndrome(int disks, size_t bytes, void **ptrs)
303626738bSChristoph Hellwig {
313626738bSChristoph Hellwig 	u8 **dptr = (u8 **)ptrs;
323626738bSChristoph Hellwig 	u8 *p, *q;
333626738bSChristoph Hellwig 	int d, z, z0;
343626738bSChristoph Hellwig 
353626738bSChristoph Hellwig 	z0 = disks - 3;		/* Highest data disk */
363626738bSChristoph Hellwig 	p = dptr[z0+1];		/* XOR parity */
373626738bSChristoph Hellwig 	q = dptr[z0+2];		/* RS syndrome */
383626738bSChristoph Hellwig 
393626738bSChristoph Hellwig 	kernel_fpu_begin();
403626738bSChristoph Hellwig 
413626738bSChristoph Hellwig 	/*
423626738bSChristoph Hellwig 	 * $vr0, $vr1, $vr2, $vr3: wp
433626738bSChristoph Hellwig 	 * $vr4, $vr5, $vr6, $vr7: wq
443626738bSChristoph Hellwig 	 * $vr8, $vr9, $vr10, $vr11: wd
453626738bSChristoph Hellwig 	 * $vr12, $vr13, $vr14, $vr15: w2
463626738bSChristoph Hellwig 	 * $vr16, $vr17, $vr18, $vr19: w1
473626738bSChristoph Hellwig 	 */
483626738bSChristoph Hellwig 	for (d = 0; d < bytes; d += NSIZE*4) {
493626738bSChristoph Hellwig 		/* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
503626738bSChristoph Hellwig 		asm volatile("vld $vr0, %0" : : "m"(dptr[z0][d+0*NSIZE]));
513626738bSChristoph Hellwig 		asm volatile("vld $vr1, %0" : : "m"(dptr[z0][d+1*NSIZE]));
523626738bSChristoph Hellwig 		asm volatile("vld $vr2, %0" : : "m"(dptr[z0][d+2*NSIZE]));
533626738bSChristoph Hellwig 		asm volatile("vld $vr3, %0" : : "m"(dptr[z0][d+3*NSIZE]));
543626738bSChristoph Hellwig 		asm volatile("vori.b $vr4, $vr0, 0");
553626738bSChristoph Hellwig 		asm volatile("vori.b $vr5, $vr1, 0");
563626738bSChristoph Hellwig 		asm volatile("vori.b $vr6, $vr2, 0");
573626738bSChristoph Hellwig 		asm volatile("vori.b $vr7, $vr3, 0");
583626738bSChristoph Hellwig 		for (z = z0-1; z >= 0; z--) {
593626738bSChristoph Hellwig 			/* wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; */
603626738bSChristoph Hellwig 			asm volatile("vld $vr8, %0" : : "m"(dptr[z][d+0*NSIZE]));
613626738bSChristoph Hellwig 			asm volatile("vld $vr9, %0" : : "m"(dptr[z][d+1*NSIZE]));
623626738bSChristoph Hellwig 			asm volatile("vld $vr10, %0" : : "m"(dptr[z][d+2*NSIZE]));
633626738bSChristoph Hellwig 			asm volatile("vld $vr11, %0" : : "m"(dptr[z][d+3*NSIZE]));
643626738bSChristoph Hellwig 			/* wp$$ ^= wd$$; */
653626738bSChristoph Hellwig 			asm volatile("vxor.v $vr0, $vr0, $vr8");
663626738bSChristoph Hellwig 			asm volatile("vxor.v $vr1, $vr1, $vr9");
673626738bSChristoph Hellwig 			asm volatile("vxor.v $vr2, $vr2, $vr10");
683626738bSChristoph Hellwig 			asm volatile("vxor.v $vr3, $vr3, $vr11");
693626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
703626738bSChristoph Hellwig 			asm volatile("vslti.b $vr12, $vr4, 0");
713626738bSChristoph Hellwig 			asm volatile("vslti.b $vr13, $vr5, 0");
723626738bSChristoph Hellwig 			asm volatile("vslti.b $vr14, $vr6, 0");
733626738bSChristoph Hellwig 			asm volatile("vslti.b $vr15, $vr7, 0");
743626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
753626738bSChristoph Hellwig 			asm volatile("vslli.b $vr16, $vr4, 1");
763626738bSChristoph Hellwig 			asm volatile("vslli.b $vr17, $vr5, 1");
773626738bSChristoph Hellwig 			asm volatile("vslli.b $vr18, $vr6, 1");
783626738bSChristoph Hellwig 			asm volatile("vslli.b $vr19, $vr7, 1");
793626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
803626738bSChristoph Hellwig 			asm volatile("vandi.b $vr12, $vr12, 0x1d");
813626738bSChristoph Hellwig 			asm volatile("vandi.b $vr13, $vr13, 0x1d");
823626738bSChristoph Hellwig 			asm volatile("vandi.b $vr14, $vr14, 0x1d");
833626738bSChristoph Hellwig 			asm volatile("vandi.b $vr15, $vr15, 0x1d");
843626738bSChristoph Hellwig 			/* w1$$ ^= w2$$; */
853626738bSChristoph Hellwig 			asm volatile("vxor.v $vr16, $vr16, $vr12");
863626738bSChristoph Hellwig 			asm volatile("vxor.v $vr17, $vr17, $vr13");
873626738bSChristoph Hellwig 			asm volatile("vxor.v $vr18, $vr18, $vr14");
883626738bSChristoph Hellwig 			asm volatile("vxor.v $vr19, $vr19, $vr15");
893626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ wd$$; */
903626738bSChristoph Hellwig 			asm volatile("vxor.v $vr4, $vr16, $vr8");
913626738bSChristoph Hellwig 			asm volatile("vxor.v $vr5, $vr17, $vr9");
923626738bSChristoph Hellwig 			asm volatile("vxor.v $vr6, $vr18, $vr10");
933626738bSChristoph Hellwig 			asm volatile("vxor.v $vr7, $vr19, $vr11");
943626738bSChristoph Hellwig 		}
953626738bSChristoph Hellwig 		/* *(unative_t *)&p[d+NSIZE*$$] = wp$$; */
963626738bSChristoph Hellwig 		asm volatile("vst $vr0, %0" : "=m"(p[d+NSIZE*0]));
973626738bSChristoph Hellwig 		asm volatile("vst $vr1, %0" : "=m"(p[d+NSIZE*1]));
983626738bSChristoph Hellwig 		asm volatile("vst $vr2, %0" : "=m"(p[d+NSIZE*2]));
993626738bSChristoph Hellwig 		asm volatile("vst $vr3, %0" : "=m"(p[d+NSIZE*3]));
1003626738bSChristoph Hellwig 		/* *(unative_t *)&q[d+NSIZE*$$] = wq$$; */
1013626738bSChristoph Hellwig 		asm volatile("vst $vr4, %0" : "=m"(q[d+NSIZE*0]));
1023626738bSChristoph Hellwig 		asm volatile("vst $vr5, %0" : "=m"(q[d+NSIZE*1]));
1033626738bSChristoph Hellwig 		asm volatile("vst $vr6, %0" : "=m"(q[d+NSIZE*2]));
1043626738bSChristoph Hellwig 		asm volatile("vst $vr7, %0" : "=m"(q[d+NSIZE*3]));
1053626738bSChristoph Hellwig 	}
1063626738bSChristoph Hellwig 
1073626738bSChristoph Hellwig 	kernel_fpu_end();
1083626738bSChristoph Hellwig }
1093626738bSChristoph Hellwig 
1103626738bSChristoph Hellwig static void raid6_lsx_xor_syndrome(int disks, int start, int stop,
1113626738bSChristoph Hellwig 				   size_t bytes, void **ptrs)
1123626738bSChristoph Hellwig {
1133626738bSChristoph Hellwig 	u8 **dptr = (u8 **)ptrs;
1143626738bSChristoph Hellwig 	u8 *p, *q;
1153626738bSChristoph Hellwig 	int d, z, z0;
1163626738bSChristoph Hellwig 
1173626738bSChristoph Hellwig 	z0 = stop;		/* P/Q right side optimization */
1183626738bSChristoph Hellwig 	p = dptr[disks-2];	/* XOR parity */
1193626738bSChristoph Hellwig 	q = dptr[disks-1];	/* RS syndrome */
1203626738bSChristoph Hellwig 
1213626738bSChristoph Hellwig 	kernel_fpu_begin();
1223626738bSChristoph Hellwig 
1233626738bSChristoph Hellwig 	/*
1243626738bSChristoph Hellwig 	 * $vr0, $vr1, $vr2, $vr3: wp
1253626738bSChristoph Hellwig 	 * $vr4, $vr5, $vr6, $vr7: wq
1263626738bSChristoph Hellwig 	 * $vr8, $vr9, $vr10, $vr11: wd
1273626738bSChristoph Hellwig 	 * $vr12, $vr13, $vr14, $vr15: w2
1283626738bSChristoph Hellwig 	 * $vr16, $vr17, $vr18, $vr19: w1
1293626738bSChristoph Hellwig 	 */
1303626738bSChristoph Hellwig 	for (d = 0; d < bytes; d += NSIZE*4) {
1313626738bSChristoph Hellwig 		/* P/Q data pages */
1323626738bSChristoph Hellwig 		/* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
1333626738bSChristoph Hellwig 		asm volatile("vld $vr0, %0" : : "m"(dptr[z0][d+0*NSIZE]));
1343626738bSChristoph Hellwig 		asm volatile("vld $vr1, %0" : : "m"(dptr[z0][d+1*NSIZE]));
1353626738bSChristoph Hellwig 		asm volatile("vld $vr2, %0" : : "m"(dptr[z0][d+2*NSIZE]));
1363626738bSChristoph Hellwig 		asm volatile("vld $vr3, %0" : : "m"(dptr[z0][d+3*NSIZE]));
1373626738bSChristoph Hellwig 		asm volatile("vori.b $vr4, $vr0, 0");
1383626738bSChristoph Hellwig 		asm volatile("vori.b $vr5, $vr1, 0");
1393626738bSChristoph Hellwig 		asm volatile("vori.b $vr6, $vr2, 0");
1403626738bSChristoph Hellwig 		asm volatile("vori.b $vr7, $vr3, 0");
1413626738bSChristoph Hellwig 		for (z = z0-1; z >= start; z--) {
1423626738bSChristoph Hellwig 			/* wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; */
1433626738bSChristoph Hellwig 			asm volatile("vld $vr8, %0" : : "m"(dptr[z][d+0*NSIZE]));
1443626738bSChristoph Hellwig 			asm volatile("vld $vr9, %0" : : "m"(dptr[z][d+1*NSIZE]));
1453626738bSChristoph Hellwig 			asm volatile("vld $vr10, %0" : : "m"(dptr[z][d+2*NSIZE]));
1463626738bSChristoph Hellwig 			asm volatile("vld $vr11, %0" : : "m"(dptr[z][d+3*NSIZE]));
1473626738bSChristoph Hellwig 			/* wp$$ ^= wd$$; */
1483626738bSChristoph Hellwig 			asm volatile("vxor.v $vr0, $vr0, $vr8");
1493626738bSChristoph Hellwig 			asm volatile("vxor.v $vr1, $vr1, $vr9");
1503626738bSChristoph Hellwig 			asm volatile("vxor.v $vr2, $vr2, $vr10");
1513626738bSChristoph Hellwig 			asm volatile("vxor.v $vr3, $vr3, $vr11");
1523626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
1533626738bSChristoph Hellwig 			asm volatile("vslti.b $vr12, $vr4, 0");
1543626738bSChristoph Hellwig 			asm volatile("vslti.b $vr13, $vr5, 0");
1553626738bSChristoph Hellwig 			asm volatile("vslti.b $vr14, $vr6, 0");
1563626738bSChristoph Hellwig 			asm volatile("vslti.b $vr15, $vr7, 0");
1573626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
1583626738bSChristoph Hellwig 			asm volatile("vslli.b $vr16, $vr4, 1");
1593626738bSChristoph Hellwig 			asm volatile("vslli.b $vr17, $vr5, 1");
1603626738bSChristoph Hellwig 			asm volatile("vslli.b $vr18, $vr6, 1");
1613626738bSChristoph Hellwig 			asm volatile("vslli.b $vr19, $vr7, 1");
1623626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
1633626738bSChristoph Hellwig 			asm volatile("vandi.b $vr12, $vr12, 0x1d");
1643626738bSChristoph Hellwig 			asm volatile("vandi.b $vr13, $vr13, 0x1d");
1653626738bSChristoph Hellwig 			asm volatile("vandi.b $vr14, $vr14, 0x1d");
1663626738bSChristoph Hellwig 			asm volatile("vandi.b $vr15, $vr15, 0x1d");
1673626738bSChristoph Hellwig 			/* w1$$ ^= w2$$; */
1683626738bSChristoph Hellwig 			asm volatile("vxor.v $vr16, $vr16, $vr12");
1693626738bSChristoph Hellwig 			asm volatile("vxor.v $vr17, $vr17, $vr13");
1703626738bSChristoph Hellwig 			asm volatile("vxor.v $vr18, $vr18, $vr14");
1713626738bSChristoph Hellwig 			asm volatile("vxor.v $vr19, $vr19, $vr15");
1723626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ wd$$; */
1733626738bSChristoph Hellwig 			asm volatile("vxor.v $vr4, $vr16, $vr8");
1743626738bSChristoph Hellwig 			asm volatile("vxor.v $vr5, $vr17, $vr9");
1753626738bSChristoph Hellwig 			asm volatile("vxor.v $vr6, $vr18, $vr10");
1763626738bSChristoph Hellwig 			asm volatile("vxor.v $vr7, $vr19, $vr11");
1773626738bSChristoph Hellwig 		}
1783626738bSChristoph Hellwig 
1793626738bSChristoph Hellwig 		/* P/Q left side optimization */
1803626738bSChristoph Hellwig 		for (z = start-1; z >= 0; z--) {
1813626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
1823626738bSChristoph Hellwig 			asm volatile("vslti.b $vr12, $vr4, 0");
1833626738bSChristoph Hellwig 			asm volatile("vslti.b $vr13, $vr5, 0");
1843626738bSChristoph Hellwig 			asm volatile("vslti.b $vr14, $vr6, 0");
1853626738bSChristoph Hellwig 			asm volatile("vslti.b $vr15, $vr7, 0");
1863626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
1873626738bSChristoph Hellwig 			asm volatile("vslli.b $vr16, $vr4, 1");
1883626738bSChristoph Hellwig 			asm volatile("vslli.b $vr17, $vr5, 1");
1893626738bSChristoph Hellwig 			asm volatile("vslli.b $vr18, $vr6, 1");
1903626738bSChristoph Hellwig 			asm volatile("vslli.b $vr19, $vr7, 1");
1913626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
1923626738bSChristoph Hellwig 			asm volatile("vandi.b $vr12, $vr12, 0x1d");
1933626738bSChristoph Hellwig 			asm volatile("vandi.b $vr13, $vr13, 0x1d");
1943626738bSChristoph Hellwig 			asm volatile("vandi.b $vr14, $vr14, 0x1d");
1953626738bSChristoph Hellwig 			asm volatile("vandi.b $vr15, $vr15, 0x1d");
1963626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ w2$$; */
1973626738bSChristoph Hellwig 			asm volatile("vxor.v $vr4, $vr16, $vr12");
1983626738bSChristoph Hellwig 			asm volatile("vxor.v $vr5, $vr17, $vr13");
1993626738bSChristoph Hellwig 			asm volatile("vxor.v $vr6, $vr18, $vr14");
2003626738bSChristoph Hellwig 			asm volatile("vxor.v $vr7, $vr19, $vr15");
2013626738bSChristoph Hellwig 		}
2023626738bSChristoph Hellwig 		/*
2033626738bSChristoph Hellwig 		 * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
2043626738bSChristoph Hellwig 		 * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
2053626738bSChristoph Hellwig 		 */
2063626738bSChristoph Hellwig 		asm volatile(
2073626738bSChristoph Hellwig 			"vld $vr20, %0\n\t"
2083626738bSChristoph Hellwig 			"vld $vr21, %1\n\t"
2093626738bSChristoph Hellwig 			"vld $vr22, %2\n\t"
2103626738bSChristoph Hellwig 			"vld $vr23, %3\n\t"
2113626738bSChristoph Hellwig 			"vld $vr24, %4\n\t"
2123626738bSChristoph Hellwig 			"vld $vr25, %5\n\t"
2133626738bSChristoph Hellwig 			"vld $vr26, %6\n\t"
2143626738bSChristoph Hellwig 			"vld $vr27, %7\n\t"
2153626738bSChristoph Hellwig 			"vxor.v $vr20, $vr20, $vr0\n\t"
2163626738bSChristoph Hellwig 			"vxor.v $vr21, $vr21, $vr1\n\t"
2173626738bSChristoph Hellwig 			"vxor.v $vr22, $vr22, $vr2\n\t"
2183626738bSChristoph Hellwig 			"vxor.v $vr23, $vr23, $vr3\n\t"
2193626738bSChristoph Hellwig 			"vxor.v $vr24, $vr24, $vr4\n\t"
2203626738bSChristoph Hellwig 			"vxor.v $vr25, $vr25, $vr5\n\t"
2213626738bSChristoph Hellwig 			"vxor.v $vr26, $vr26, $vr6\n\t"
2223626738bSChristoph Hellwig 			"vxor.v $vr27, $vr27, $vr7\n\t"
2233626738bSChristoph Hellwig 			"vst $vr20, %0\n\t"
2243626738bSChristoph Hellwig 			"vst $vr21, %1\n\t"
2253626738bSChristoph Hellwig 			"vst $vr22, %2\n\t"
2263626738bSChristoph Hellwig 			"vst $vr23, %3\n\t"
2273626738bSChristoph Hellwig 			"vst $vr24, %4\n\t"
2283626738bSChristoph Hellwig 			"vst $vr25, %5\n\t"
2293626738bSChristoph Hellwig 			"vst $vr26, %6\n\t"
2303626738bSChristoph Hellwig 			"vst $vr27, %7\n\t"
2313626738bSChristoph Hellwig 			: "+m"(p[d+NSIZE*0]), "+m"(p[d+NSIZE*1]),
2323626738bSChristoph Hellwig 			  "+m"(p[d+NSIZE*2]), "+m"(p[d+NSIZE*3]),
2333626738bSChristoph Hellwig 			  "+m"(q[d+NSIZE*0]), "+m"(q[d+NSIZE*1]),
2343626738bSChristoph Hellwig 			  "+m"(q[d+NSIZE*2]), "+m"(q[d+NSIZE*3])
2353626738bSChristoph Hellwig 		);
2363626738bSChristoph Hellwig 	}
2373626738bSChristoph Hellwig 
2383626738bSChristoph Hellwig 	kernel_fpu_end();
2393626738bSChristoph Hellwig }
2403626738bSChristoph Hellwig 
2413626738bSChristoph Hellwig const struct raid6_calls raid6_lsx = {
2427e91f76aSChristoph Hellwig 	.gen_syndrome	= raid6_lsx_gen_syndrome,
2437e91f76aSChristoph Hellwig 	.xor_syndrome	= raid6_lsx_xor_syndrome,
2447e91f76aSChristoph Hellwig 	.name		= "lsx",
2453626738bSChristoph Hellwig };
2463626738bSChristoph Hellwig 
2473626738bSChristoph Hellwig #undef NSIZE
2483626738bSChristoph Hellwig #endif /* CONFIG_CPU_HAS_LSX */
2493626738bSChristoph Hellwig 
2503626738bSChristoph Hellwig #ifdef CONFIG_CPU_HAS_LASX
2513626738bSChristoph Hellwig #define NSIZE 32
2523626738bSChristoph Hellwig 
2533626738bSChristoph Hellwig static void raid6_lasx_gen_syndrome(int disks, size_t bytes, void **ptrs)
2543626738bSChristoph Hellwig {
2553626738bSChristoph Hellwig 	u8 **dptr = (u8 **)ptrs;
2563626738bSChristoph Hellwig 	u8 *p, *q;
2573626738bSChristoph Hellwig 	int d, z, z0;
2583626738bSChristoph Hellwig 
2593626738bSChristoph Hellwig 	z0 = disks - 3;		/* Highest data disk */
2603626738bSChristoph Hellwig 	p = dptr[z0+1];		/* XOR parity */
2613626738bSChristoph Hellwig 	q = dptr[z0+2];		/* RS syndrome */
2623626738bSChristoph Hellwig 
2633626738bSChristoph Hellwig 	kernel_fpu_begin();
2643626738bSChristoph Hellwig 
2653626738bSChristoph Hellwig 	/*
2663626738bSChristoph Hellwig 	 * $xr0, $xr1: wp
2673626738bSChristoph Hellwig 	 * $xr2, $xr3: wq
2683626738bSChristoph Hellwig 	 * $xr4, $xr5: wd
2693626738bSChristoph Hellwig 	 * $xr6, $xr7: w2
2703626738bSChristoph Hellwig 	 * $xr8, $xr9: w1
2713626738bSChristoph Hellwig 	 */
2723626738bSChristoph Hellwig 	for (d = 0; d < bytes; d += NSIZE*2) {
2733626738bSChristoph Hellwig 		/* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
2743626738bSChristoph Hellwig 		asm volatile("xvld $xr0, %0" : : "m"(dptr[z0][d+0*NSIZE]));
2753626738bSChristoph Hellwig 		asm volatile("xvld $xr1, %0" : : "m"(dptr[z0][d+1*NSIZE]));
2763626738bSChristoph Hellwig 		asm volatile("xvori.b $xr2, $xr0, 0");
2773626738bSChristoph Hellwig 		asm volatile("xvori.b $xr3, $xr1, 0");
2783626738bSChristoph Hellwig 		for (z = z0-1; z >= 0; z--) {
2793626738bSChristoph Hellwig 			/* wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; */
2803626738bSChristoph Hellwig 			asm volatile("xvld $xr4, %0" : : "m"(dptr[z][d+0*NSIZE]));
2813626738bSChristoph Hellwig 			asm volatile("xvld $xr5, %0" : : "m"(dptr[z][d+1*NSIZE]));
2823626738bSChristoph Hellwig 			/* wp$$ ^= wd$$; */
2833626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr0, $xr0, $xr4");
2843626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr1, $xr1, $xr5");
2853626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
2863626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr6, $xr2, 0");
2873626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr7, $xr3, 0");
2883626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
2893626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr8, $xr2, 1");
2903626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr9, $xr3, 1");
2913626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
2923626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr6, $xr6, 0x1d");
2933626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr7, $xr7, 0x1d");
2943626738bSChristoph Hellwig 			/* w1$$ ^= w2$$; */
2953626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr8, $xr8, $xr6");
2963626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr9, $xr9, $xr7");
2973626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ wd$$; */
2983626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr2, $xr8, $xr4");
2993626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr3, $xr9, $xr5");
3003626738bSChristoph Hellwig 		}
3013626738bSChristoph Hellwig 		/* *(unative_t *)&p[d+NSIZE*$$] = wp$$; */
3023626738bSChristoph Hellwig 		asm volatile("xvst $xr0, %0" : "=m"(p[d+NSIZE*0]));
3033626738bSChristoph Hellwig 		asm volatile("xvst $xr1, %0" : "=m"(p[d+NSIZE*1]));
3043626738bSChristoph Hellwig 		/* *(unative_t *)&q[d+NSIZE*$$] = wq$$; */
3053626738bSChristoph Hellwig 		asm volatile("xvst $xr2, %0" : "=m"(q[d+NSIZE*0]));
3063626738bSChristoph Hellwig 		asm volatile("xvst $xr3, %0" : "=m"(q[d+NSIZE*1]));
3073626738bSChristoph Hellwig 	}
3083626738bSChristoph Hellwig 
3093626738bSChristoph Hellwig 	kernel_fpu_end();
3103626738bSChristoph Hellwig }
3113626738bSChristoph Hellwig 
3123626738bSChristoph Hellwig static void raid6_lasx_xor_syndrome(int disks, int start, int stop,
3133626738bSChristoph Hellwig 				    size_t bytes, void **ptrs)
3143626738bSChristoph Hellwig {
3153626738bSChristoph Hellwig 	u8 **dptr = (u8 **)ptrs;
3163626738bSChristoph Hellwig 	u8 *p, *q;
3173626738bSChristoph Hellwig 	int d, z, z0;
3183626738bSChristoph Hellwig 
3193626738bSChristoph Hellwig 	z0 = stop;		/* P/Q right side optimization */
3203626738bSChristoph Hellwig 	p = dptr[disks-2];	/* XOR parity */
3213626738bSChristoph Hellwig 	q = dptr[disks-1];	/* RS syndrome */
3223626738bSChristoph Hellwig 
3233626738bSChristoph Hellwig 	kernel_fpu_begin();
3243626738bSChristoph Hellwig 
3253626738bSChristoph Hellwig 	/*
3263626738bSChristoph Hellwig 	 * $xr0, $xr1: wp
3273626738bSChristoph Hellwig 	 * $xr2, $xr3: wq
3283626738bSChristoph Hellwig 	 * $xr4, $xr5: wd
3293626738bSChristoph Hellwig 	 * $xr6, $xr7: w2
3303626738bSChristoph Hellwig 	 * $xr8, $xr9: w1
3313626738bSChristoph Hellwig 	 */
3323626738bSChristoph Hellwig 	for (d = 0; d < bytes; d += NSIZE*2) {
3333626738bSChristoph Hellwig 		/* P/Q data pages */
3343626738bSChristoph Hellwig 		/* wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; */
3353626738bSChristoph Hellwig 		asm volatile("xvld $xr0, %0" : : "m"(dptr[z0][d+0*NSIZE]));
3363626738bSChristoph Hellwig 		asm volatile("xvld $xr1, %0" : : "m"(dptr[z0][d+1*NSIZE]));
3373626738bSChristoph Hellwig 		asm volatile("xvori.b $xr2, $xr0, 0");
3383626738bSChristoph Hellwig 		asm volatile("xvori.b $xr3, $xr1, 0");
3393626738bSChristoph Hellwig 		for (z = z0-1; z >= start; z--) {
3403626738bSChristoph Hellwig 			/* wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; */
3413626738bSChristoph Hellwig 			asm volatile("xvld $xr4, %0" : : "m"(dptr[z][d+0*NSIZE]));
3423626738bSChristoph Hellwig 			asm volatile("xvld $xr5, %0" : : "m"(dptr[z][d+1*NSIZE]));
3433626738bSChristoph Hellwig 			/* wp$$ ^= wd$$; */
3443626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr0, $xr0, $xr4");
3453626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr1, $xr1, $xr5");
3463626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
3473626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr6, $xr2, 0");
3483626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr7, $xr3, 0");
3493626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
3503626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr8, $xr2, 1");
3513626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr9, $xr3, 1");
3523626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
3533626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr6, $xr6, 0x1d");
3543626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr7, $xr7, 0x1d");
3553626738bSChristoph Hellwig 			/* w1$$ ^= w2$$; */
3563626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr8, $xr8, $xr6");
3573626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr9, $xr9, $xr7");
3583626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ wd$$; */
3593626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr2, $xr8, $xr4");
3603626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr3, $xr9, $xr5");
3613626738bSChristoph Hellwig 		}
3623626738bSChristoph Hellwig 
3633626738bSChristoph Hellwig 		/* P/Q left side optimization */
3643626738bSChristoph Hellwig 		for (z = start-1; z >= 0; z--) {
3653626738bSChristoph Hellwig 			/* w2$$ = MASK(wq$$); */
3663626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr6, $xr2, 0");
3673626738bSChristoph Hellwig 			asm volatile("xvslti.b $xr7, $xr3, 0");
3683626738bSChristoph Hellwig 			/* w1$$ = SHLBYTE(wq$$); */
3693626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr8, $xr2, 1");
3703626738bSChristoph Hellwig 			asm volatile("xvslli.b $xr9, $xr3, 1");
3713626738bSChristoph Hellwig 			/* w2$$ &= NBYTES(0x1d); */
3723626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr6, $xr6, 0x1d");
3733626738bSChristoph Hellwig 			asm volatile("xvandi.b $xr7, $xr7, 0x1d");
3743626738bSChristoph Hellwig 			/* wq$$ = w1$$ ^ w2$$; */
3753626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr2, $xr8, $xr6");
3763626738bSChristoph Hellwig 			asm volatile("xvxor.v $xr3, $xr9, $xr7");
3773626738bSChristoph Hellwig 		}
3783626738bSChristoph Hellwig 		/*
3793626738bSChristoph Hellwig 		 * *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
3803626738bSChristoph Hellwig 		 * *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
3813626738bSChristoph Hellwig 		 */
3823626738bSChristoph Hellwig 		asm volatile(
3833626738bSChristoph Hellwig 			"xvld $xr10, %0\n\t"
3843626738bSChristoph Hellwig 			"xvld $xr11, %1\n\t"
3853626738bSChristoph Hellwig 			"xvld $xr12, %2\n\t"
3863626738bSChristoph Hellwig 			"xvld $xr13, %3\n\t"
3873626738bSChristoph Hellwig 			"xvxor.v $xr10, $xr10, $xr0\n\t"
3883626738bSChristoph Hellwig 			"xvxor.v $xr11, $xr11, $xr1\n\t"
3893626738bSChristoph Hellwig 			"xvxor.v $xr12, $xr12, $xr2\n\t"
3903626738bSChristoph Hellwig 			"xvxor.v $xr13, $xr13, $xr3\n\t"
3913626738bSChristoph Hellwig 			"xvst $xr10, %0\n\t"
3923626738bSChristoph Hellwig 			"xvst $xr11, %1\n\t"
3933626738bSChristoph Hellwig 			"xvst $xr12, %2\n\t"
3943626738bSChristoph Hellwig 			"xvst $xr13, %3\n\t"
3953626738bSChristoph Hellwig 			: "+m"(p[d+NSIZE*0]), "+m"(p[d+NSIZE*1]),
3963626738bSChristoph Hellwig 			  "+m"(q[d+NSIZE*0]), "+m"(q[d+NSIZE*1])
3973626738bSChristoph Hellwig 		);
3983626738bSChristoph Hellwig 	}
3993626738bSChristoph Hellwig 
4003626738bSChristoph Hellwig 	kernel_fpu_end();
4013626738bSChristoph Hellwig }
4023626738bSChristoph Hellwig 
4033626738bSChristoph Hellwig const struct raid6_calls raid6_lasx = {
4047e91f76aSChristoph Hellwig 	.gen_syndrome	= raid6_lasx_gen_syndrome,
4057e91f76aSChristoph Hellwig 	.xor_syndrome	= raid6_lasx_xor_syndrome,
4067e91f76aSChristoph Hellwig 	.name		= "lasx",
4073626738bSChristoph Hellwig };
4083626738bSChristoph Hellwig #undef NSIZE
4093626738bSChristoph Hellwig #endif /* CONFIG_CPU_HAS_LASX */
410