0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/export.h>
0010 #include <linux/raid/pq.h>
0011
0012 static inline void xor_block(u8 *p1, u8 *p2)
0013 {
0014 typedef struct { u8 _[256]; } addrtype;
0015
0016 asm volatile(
0017 " xc 0(256,%[p1]),0(%[p2])\n"
0018 : "+m" (*(addrtype *) p1) : "m" (*(addrtype *) p2),
0019 [p1] "a" (p1), [p2] "a" (p2) : "cc");
0020 }
0021
0022
0023 static void raid6_2data_recov_s390xc(int disks, size_t bytes, int faila,
0024 int failb, void **ptrs)
0025 {
0026 u8 *p, *q, *dp, *dq;
0027 const u8 *pbmul;
0028 const u8 *qmul;
0029 int i;
0030
0031 p = (u8 *)ptrs[disks-2];
0032 q = (u8 *)ptrs[disks-1];
0033
0034
0035
0036
0037 dp = (u8 *)ptrs[faila];
0038 ptrs[faila] = (void *)raid6_empty_zero_page;
0039 ptrs[disks-2] = dp;
0040 dq = (u8 *)ptrs[failb];
0041 ptrs[failb] = (void *)raid6_empty_zero_page;
0042 ptrs[disks-1] = dq;
0043
0044 raid6_call.gen_syndrome(disks, bytes, ptrs);
0045
0046
0047 ptrs[faila] = dp;
0048 ptrs[failb] = dq;
0049 ptrs[disks-2] = p;
0050 ptrs[disks-1] = q;
0051
0052
0053 pbmul = raid6_gfmul[raid6_gfexi[failb-faila]];
0054 qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]^raid6_gfexp[failb]]];
0055
0056
0057 while (bytes) {
0058 xor_block(dp, p);
0059 xor_block(dq, q);
0060 for (i = 0; i < 256; i++)
0061 dq[i] = pbmul[dp[i]] ^ qmul[dq[i]];
0062 xor_block(dp, dq);
0063 p += 256;
0064 q += 256;
0065 dp += 256;
0066 dq += 256;
0067 bytes -= 256;
0068 }
0069 }
0070
0071
0072 static void raid6_datap_recov_s390xc(int disks, size_t bytes, int faila,
0073 void **ptrs)
0074 {
0075 u8 *p, *q, *dq;
0076 const u8 *qmul;
0077 int i;
0078
0079 p = (u8 *)ptrs[disks-2];
0080 q = (u8 *)ptrs[disks-1];
0081
0082
0083
0084 dq = (u8 *)ptrs[faila];
0085 ptrs[faila] = (void *)raid6_empty_zero_page;
0086 ptrs[disks-1] = dq;
0087
0088 raid6_call.gen_syndrome(disks, bytes, ptrs);
0089
0090
0091 ptrs[faila] = dq;
0092 ptrs[disks-1] = q;
0093
0094
0095 qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[faila]]];
0096
0097
0098 while (bytes) {
0099 xor_block(dq, q);
0100 for (i = 0; i < 256; i++)
0101 dq[i] = qmul[dq[i]];
0102 xor_block(p, dq);
0103 p += 256;
0104 q += 256;
0105 dq += 256;
0106 bytes -= 256;
0107 }
0108 }
0109
0110
0111 const struct raid6_recov_calls raid6_recov_s390xc = {
0112 .data2 = raid6_2data_recov_s390xc,
0113 .datap = raid6_datap_recov_s390xc,
0114 .valid = NULL,
0115 .name = "s390xc",
0116 .priority = 1,
0117 };