#include <linux/raid/pq.h>
#include "rvv.h"
static void __raid6_2data_recov_rvv(int bytes, u8 *p, u8 *q, u8 *dp,
u8 *dq, const u8 *pbmul,
const u8 *qmul)
{
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli x0, %[avl], e8, m1, ta, ma\n"
".option pop\n"
: :
[avl]"r"(16)
);
while (bytes) {
asm volatile (".option push\n"
".option arch,+v\n"
"vle8.v v0, (%[px])\n"
"vle8.v v1, (%[dp])\n"
"vxor.vv v0, v0, v1\n"
"vle8.v v2, (%[qx])\n"
"vle8.v v3, (%[dq])\n"
"vxor.vv v4, v2, v3\n"
"vsrl.vi v5, v4, 4\n"
"vand.vi v4, v4, 0xf\n"
"vle8.v v6, (%[qm0])\n"
"vle8.v v7, (%[qm1])\n"
"vrgather.vv v14, v6, v4\n"
"vrgather.vv v15, v7, v5\n"
"vxor.vv v2, v14, v15\n"
"vsrl.vi v5, v0, 4\n"
"vand.vi v4, v0, 0xf\n"
"vle8.v v8, (%[pm0])\n"
"vle8.v v9, (%[pm1])\n"
"vrgather.vv v14, v8, v4\n"
"vrgather.vv v15, v9, v5\n"
"vxor.vv v4, v14, v15\n"
"vxor.vv v3, v4, v2\n"
"vxor.vv v1, v3, v0\n"
"vse8.v v3, (%[dq])\n"
"vse8.v v1, (%[dp])\n"
".option pop\n"
: :
[px]"r"(p),
[dp]"r"(dp),
[qx]"r"(q),
[dq]"r"(dq),
[qm0]"r"(qmul),
[qm1]"r"(qmul + 16),
[pm0]"r"(pbmul),
[pm1]"r"(pbmul + 16)
:);
bytes -= 16;
p += 16;
q += 16;
dp += 16;
dq += 16;
}
}
static void __raid6_datap_recov_rvv(int bytes, u8 *p, u8 *q,
u8 *dq, const u8 *qmul)
{
asm volatile (".option push\n"
".option arch,+v\n"
"vsetvli x0, %[avl], e8, m1, ta, ma\n"
".option pop\n"
: :
[avl]"r"(16)
);
while (bytes) {
asm volatile (".option push\n"
".option arch,+v\n"
"vle8.v v0, (%[vx])\n"
"vle8.v v2, (%[dq])\n"
"vxor.vv v0, v0, v2\n"
"vsrl.vi v1, v0, 4\n"
"vand.vi v0, v0, 0xf\n"
"vle8.v v4, (%[qm0])\n"
"vle8.v v5, (%[qm1])\n"
"vrgather.vv v10, v4, v0\n"
"vrgather.vv v11, v5, v1\n"
"vxor.vv v0, v10, v11\n"
"vle8.v v1, (%[vy])\n"
"vxor.vv v1, v0, v1\n"
"vse8.v v0, (%[dq])\n"
"vse8.v v1, (%[vy])\n"
".option pop\n"
: :
[vx]"r"(q),
[vy]"r"(p),
[dq]"r"(dq),
[qm0]"r"(qmul),
[qm1]"r"(qmul + 16)
:);
bytes -= 16;
p += 16;
q += 16;
dq += 16;
}
}
static void raid6_2data_recov_rvv(int disks, size_t bytes, int faila,
int failb, void **ptrs)
{
u8 *p, *q, *dp, *dq;
const u8 *pbmul;
const u8 *qmul;
p = (u8 *)ptrs[disks - 2];
q = (u8 *)ptrs[disks - 1];
dp = (u8 *)ptrs[faila];
ptrs[faila] = raid6_get_zero_page();
ptrs[disks - 2] = dp;
dq = (u8 *)ptrs[failb];
ptrs[failb] = raid6_get_zero_page();
ptrs[disks - 1] = dq;
raid6_call.gen_syndrome(disks, bytes, ptrs);
ptrs[faila] = dp;
ptrs[failb] = dq;
ptrs[disks - 2] = p;
ptrs[disks - 1] = q;
pbmul = raid6_vgfmul[raid6_gfexi[failb - faila]];
qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^
raid6_gfexp[failb]]];
kernel_vector_begin();
__raid6_2data_recov_rvv(bytes, p, q, dp, dq, pbmul, qmul);
kernel_vector_end();
}
static void raid6_datap_recov_rvv(int disks, size_t bytes, int faila,
void **ptrs)
{
u8 *p, *q, *dq;
const u8 *qmul;
p = (u8 *)ptrs[disks - 2];
q = (u8 *)ptrs[disks - 1];
dq = (u8 *)ptrs[faila];
ptrs[faila] = raid6_get_zero_page();
ptrs[disks - 1] = dq;
raid6_call.gen_syndrome(disks, bytes, ptrs);
ptrs[faila] = dq;
ptrs[disks - 1] = q;
qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]];
kernel_vector_begin();
__raid6_datap_recov_rvv(bytes, p, q, dq, qmul);
kernel_vector_end();
}
const struct raid6_recov_calls raid6_recov_rvv = {
.data2 = raid6_2data_recov_rvv,
.datap = raid6_datap_recov_rvv,
.valid = rvv_has_vector,
.name = "rvv",
.priority = 1,
};