18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Optimized xor_block operation for RAID4/5
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2016
68c2ecf20Sopenharmony_ci * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci#include <linux/export.h>
118c2ecf20Sopenharmony_ci#include <linux/raid/xor.h>
128c2ecf20Sopenharmony_ci#include <asm/xor.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic void xor_xc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	asm volatile(
178c2ecf20Sopenharmony_ci		"	larl	1,2f\n"
188c2ecf20Sopenharmony_ci		"	aghi	%0,-1\n"
198c2ecf20Sopenharmony_ci		"	jm	3f\n"
208c2ecf20Sopenharmony_ci		"	srlg	0,%0,8\n"
218c2ecf20Sopenharmony_ci		"	ltgr	0,0\n"
228c2ecf20Sopenharmony_ci		"	jz	1f\n"
238c2ecf20Sopenharmony_ci		"0:	xc	0(256,%1),0(%2)\n"
248c2ecf20Sopenharmony_ci		"	la	%1,256(%1)\n"
258c2ecf20Sopenharmony_ci		"	la	%2,256(%2)\n"
268c2ecf20Sopenharmony_ci		"	brctg	0,0b\n"
278c2ecf20Sopenharmony_ci		"1:	ex	%0,0(1)\n"
288c2ecf20Sopenharmony_ci		"	j	3f\n"
298c2ecf20Sopenharmony_ci		"2:	xc	0(1,%1),0(%2)\n"
308c2ecf20Sopenharmony_ci		"3:\n"
318c2ecf20Sopenharmony_ci		: : "d" (bytes), "a" (p1), "a" (p2)
328c2ecf20Sopenharmony_ci		: "0", "1", "cc", "memory");
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic void xor_xc_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
368c2ecf20Sopenharmony_ci		     unsigned long *p3)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	asm volatile(
398c2ecf20Sopenharmony_ci		"	larl	1,2f\n"
408c2ecf20Sopenharmony_ci		"	aghi	%0,-1\n"
418c2ecf20Sopenharmony_ci		"	jm	3f\n"
428c2ecf20Sopenharmony_ci		"	srlg	0,%0,8\n"
438c2ecf20Sopenharmony_ci		"	ltgr	0,0\n"
448c2ecf20Sopenharmony_ci		"	jz	1f\n"
458c2ecf20Sopenharmony_ci		"0:	xc	0(256,%1),0(%2)\n"
468c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%3)\n"
478c2ecf20Sopenharmony_ci		"	la	%1,256(%1)\n"
488c2ecf20Sopenharmony_ci		"	la	%2,256(%2)\n"
498c2ecf20Sopenharmony_ci		"	la	%3,256(%3)\n"
508c2ecf20Sopenharmony_ci		"	brctg	0,0b\n"
518c2ecf20Sopenharmony_ci		"1:	ex	%0,0(1)\n"
528c2ecf20Sopenharmony_ci		"	ex	%0,6(1)\n"
538c2ecf20Sopenharmony_ci		"	j	3f\n"
548c2ecf20Sopenharmony_ci		"2:	xc	0(1,%1),0(%2)\n"
558c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%3)\n"
568c2ecf20Sopenharmony_ci		"3:\n"
578c2ecf20Sopenharmony_ci		: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3)
588c2ecf20Sopenharmony_ci		: : "0", "1", "cc", "memory");
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic void xor_xc_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
628c2ecf20Sopenharmony_ci		     unsigned long *p3, unsigned long *p4)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	asm volatile(
658c2ecf20Sopenharmony_ci		"	larl	1,2f\n"
668c2ecf20Sopenharmony_ci		"	aghi	%0,-1\n"
678c2ecf20Sopenharmony_ci		"	jm	3f\n"
688c2ecf20Sopenharmony_ci		"	srlg	0,%0,8\n"
698c2ecf20Sopenharmony_ci		"	ltgr	0,0\n"
708c2ecf20Sopenharmony_ci		"	jz	1f\n"
718c2ecf20Sopenharmony_ci		"0:	xc	0(256,%1),0(%2)\n"
728c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%3)\n"
738c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%4)\n"
748c2ecf20Sopenharmony_ci		"	la	%1,256(%1)\n"
758c2ecf20Sopenharmony_ci		"	la	%2,256(%2)\n"
768c2ecf20Sopenharmony_ci		"	la	%3,256(%3)\n"
778c2ecf20Sopenharmony_ci		"	la	%4,256(%4)\n"
788c2ecf20Sopenharmony_ci		"	brctg	0,0b\n"
798c2ecf20Sopenharmony_ci		"1:	ex	%0,0(1)\n"
808c2ecf20Sopenharmony_ci		"	ex	%0,6(1)\n"
818c2ecf20Sopenharmony_ci		"	ex	%0,12(1)\n"
828c2ecf20Sopenharmony_ci		"	j	3f\n"
838c2ecf20Sopenharmony_ci		"2:	xc	0(1,%1),0(%2)\n"
848c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%3)\n"
858c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%4)\n"
868c2ecf20Sopenharmony_ci		"3:\n"
878c2ecf20Sopenharmony_ci		: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4)
888c2ecf20Sopenharmony_ci		: : "0", "1", "cc", "memory");
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic void xor_xc_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
928c2ecf20Sopenharmony_ci		     unsigned long *p3, unsigned long *p4, unsigned long *p5)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	/* Get around a gcc oddity */
958c2ecf20Sopenharmony_ci	register unsigned long *reg7 asm ("7") = p5;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	asm volatile(
988c2ecf20Sopenharmony_ci		"	larl	1,2f\n"
998c2ecf20Sopenharmony_ci		"	aghi	%0,-1\n"
1008c2ecf20Sopenharmony_ci		"	jm	3f\n"
1018c2ecf20Sopenharmony_ci		"	srlg	0,%0,8\n"
1028c2ecf20Sopenharmony_ci		"	ltgr	0,0\n"
1038c2ecf20Sopenharmony_ci		"	jz	1f\n"
1048c2ecf20Sopenharmony_ci		"0:	xc	0(256,%1),0(%2)\n"
1058c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%3)\n"
1068c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%4)\n"
1078c2ecf20Sopenharmony_ci		"	xc	0(256,%1),0(%5)\n"
1088c2ecf20Sopenharmony_ci		"	la	%1,256(%1)\n"
1098c2ecf20Sopenharmony_ci		"	la	%2,256(%2)\n"
1108c2ecf20Sopenharmony_ci		"	la	%3,256(%3)\n"
1118c2ecf20Sopenharmony_ci		"	la	%4,256(%4)\n"
1128c2ecf20Sopenharmony_ci		"	la	%5,256(%5)\n"
1138c2ecf20Sopenharmony_ci		"	brctg	0,0b\n"
1148c2ecf20Sopenharmony_ci		"1:	ex	%0,0(1)\n"
1158c2ecf20Sopenharmony_ci		"	ex	%0,6(1)\n"
1168c2ecf20Sopenharmony_ci		"	ex	%0,12(1)\n"
1178c2ecf20Sopenharmony_ci		"	ex	%0,18(1)\n"
1188c2ecf20Sopenharmony_ci		"	j	3f\n"
1198c2ecf20Sopenharmony_ci		"2:	xc	0(1,%1),0(%2)\n"
1208c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%3)\n"
1218c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%4)\n"
1228c2ecf20Sopenharmony_ci		"	xc	0(1,%1),0(%5)\n"
1238c2ecf20Sopenharmony_ci		"3:\n"
1248c2ecf20Sopenharmony_ci		: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4),
1258c2ecf20Sopenharmony_ci		  "+a" (reg7)
1268c2ecf20Sopenharmony_ci		: : "0", "1", "cc", "memory");
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistruct xor_block_template xor_block_xc = {
1308c2ecf20Sopenharmony_ci	.name = "xc",
1318c2ecf20Sopenharmony_ci	.do_2 = xor_xc_2,
1328c2ecf20Sopenharmony_ci	.do_3 = xor_xc_3,
1338c2ecf20Sopenharmony_ci	.do_4 = xor_xc_4,
1348c2ecf20Sopenharmony_ci	.do_5 = xor_xc_5,
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(xor_block_xc);
137