13626738bSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-only 23626738bSChristoph Hellwig /* 33626738bSChristoph Hellwig * RAID6 recovery algorithms in LoongArch SIMD (LSX & LASX) 43626738bSChristoph Hellwig * 53626738bSChristoph Hellwig * Copyright (C) 2023 WANG Xuerui <git@xen0n.name> 63626738bSChristoph Hellwig * 73626738bSChristoph Hellwig * Originally based on recov_avx2.c and recov_ssse3.c: 83626738bSChristoph Hellwig * 93626738bSChristoph Hellwig * Copyright (C) 2012 Intel Corporation 103626738bSChristoph Hellwig * Author: Jim Kukunas <james.t.kukunas@linux.intel.com> 113626738bSChristoph Hellwig */ 123626738bSChristoph Hellwig 13*769d603fSChristoph Hellwig #include <linux/mm.h> 143626738bSChristoph Hellwig #include <linux/raid/pq.h> 153626738bSChristoph Hellwig #include <asm/cpu-features.h> 163626738bSChristoph Hellwig #include <asm/fpu.h> 17*769d603fSChristoph Hellwig #include "algos.h" 183626738bSChristoph Hellwig 193626738bSChristoph Hellwig /* 203626738bSChristoph Hellwig * Unlike with the syndrome calculation algorithms, there's no boot-time 213626738bSChristoph Hellwig * selection of recovery algorithms by benchmarking, so we have to specify 223626738bSChristoph Hellwig * the priorities and hope the future cores will all have decent vector 233626738bSChristoph Hellwig * support (i.e. no LASX slower than LSX, or even scalar code). 243626738bSChristoph Hellwig */ 253626738bSChristoph Hellwig 263626738bSChristoph Hellwig #ifdef CONFIG_CPU_HAS_LSX 273626738bSChristoph Hellwig static void raid6_2data_recov_lsx(int disks, size_t bytes, int faila, 283626738bSChristoph Hellwig int failb, void **ptrs) 293626738bSChristoph Hellwig { 303626738bSChristoph Hellwig u8 *p, *q, *dp, *dq; 313626738bSChristoph Hellwig const u8 *pbmul; /* P multiplier table for B data */ 323626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table (for both) */ 333626738bSChristoph Hellwig 343626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 353626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 363626738bSChristoph Hellwig 373626738bSChristoph Hellwig /* 383626738bSChristoph Hellwig * Compute syndrome with zero for the missing data pages 393626738bSChristoph Hellwig * Use the dead data pages as temporary storage for 403626738bSChristoph Hellwig * delta p and delta q 413626738bSChristoph Hellwig */ 423626738bSChristoph Hellwig dp = (u8 *)ptrs[faila]; 43885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 443626738bSChristoph Hellwig ptrs[disks - 2] = dp; 453626738bSChristoph Hellwig dq = (u8 *)ptrs[failb]; 46885d3142SChristoph Hellwig ptrs[failb] = page_address(ZERO_PAGE(0)); 473626738bSChristoph Hellwig ptrs[disks - 1] = dq; 483626738bSChristoph Hellwig 4935472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 503626738bSChristoph Hellwig 513626738bSChristoph Hellwig /* Restore pointer table */ 523626738bSChristoph Hellwig ptrs[faila] = dp; 533626738bSChristoph Hellwig ptrs[failb] = dq; 543626738bSChristoph Hellwig ptrs[disks - 2] = p; 553626738bSChristoph Hellwig ptrs[disks - 1] = q; 563626738bSChristoph Hellwig 573626738bSChristoph Hellwig /* Now, pick the proper data tables */ 583626738bSChristoph Hellwig pbmul = raid6_vgfmul[raid6_gfexi[failb - faila]]; 593626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^ raid6_gfexp[failb]]]; 603626738bSChristoph Hellwig 613626738bSChristoph Hellwig kernel_fpu_begin(); 623626738bSChristoph Hellwig 633626738bSChristoph Hellwig /* 643626738bSChristoph Hellwig * vr20, vr21: qmul 653626738bSChristoph Hellwig * vr22, vr23: pbmul 663626738bSChristoph Hellwig */ 673626738bSChristoph Hellwig asm volatile("vld $vr20, %0" : : "m" (qmul[0])); 683626738bSChristoph Hellwig asm volatile("vld $vr21, %0" : : "m" (qmul[16])); 693626738bSChristoph Hellwig asm volatile("vld $vr22, %0" : : "m" (pbmul[0])); 703626738bSChristoph Hellwig asm volatile("vld $vr23, %0" : : "m" (pbmul[16])); 713626738bSChristoph Hellwig 723626738bSChristoph Hellwig while (bytes) { 733626738bSChristoph Hellwig /* vr4 - vr7: Q */ 743626738bSChristoph Hellwig asm volatile("vld $vr4, %0" : : "m" (q[0])); 753626738bSChristoph Hellwig asm volatile("vld $vr5, %0" : : "m" (q[16])); 763626738bSChristoph Hellwig asm volatile("vld $vr6, %0" : : "m" (q[32])); 773626738bSChristoph Hellwig asm volatile("vld $vr7, %0" : : "m" (q[48])); 783626738bSChristoph Hellwig /* vr4 - vr7: Q + Qxy */ 793626738bSChristoph Hellwig asm volatile("vld $vr8, %0" : : "m" (dq[0])); 803626738bSChristoph Hellwig asm volatile("vld $vr9, %0" : : "m" (dq[16])); 813626738bSChristoph Hellwig asm volatile("vld $vr10, %0" : : "m" (dq[32])); 823626738bSChristoph Hellwig asm volatile("vld $vr11, %0" : : "m" (dq[48])); 833626738bSChristoph Hellwig asm volatile("vxor.v $vr4, $vr4, $vr8"); 843626738bSChristoph Hellwig asm volatile("vxor.v $vr5, $vr5, $vr9"); 853626738bSChristoph Hellwig asm volatile("vxor.v $vr6, $vr6, $vr10"); 863626738bSChristoph Hellwig asm volatile("vxor.v $vr7, $vr7, $vr11"); 873626738bSChristoph Hellwig /* vr0 - vr3: P */ 883626738bSChristoph Hellwig asm volatile("vld $vr0, %0" : : "m" (p[0])); 893626738bSChristoph Hellwig asm volatile("vld $vr1, %0" : : "m" (p[16])); 903626738bSChristoph Hellwig asm volatile("vld $vr2, %0" : : "m" (p[32])); 913626738bSChristoph Hellwig asm volatile("vld $vr3, %0" : : "m" (p[48])); 923626738bSChristoph Hellwig /* vr0 - vr3: P + Pxy */ 933626738bSChristoph Hellwig asm volatile("vld $vr8, %0" : : "m" (dp[0])); 943626738bSChristoph Hellwig asm volatile("vld $vr9, %0" : : "m" (dp[16])); 953626738bSChristoph Hellwig asm volatile("vld $vr10, %0" : : "m" (dp[32])); 963626738bSChristoph Hellwig asm volatile("vld $vr11, %0" : : "m" (dp[48])); 973626738bSChristoph Hellwig asm volatile("vxor.v $vr0, $vr0, $vr8"); 983626738bSChristoph Hellwig asm volatile("vxor.v $vr1, $vr1, $vr9"); 993626738bSChristoph Hellwig asm volatile("vxor.v $vr2, $vr2, $vr10"); 1003626738bSChristoph Hellwig asm volatile("vxor.v $vr3, $vr3, $vr11"); 1013626738bSChristoph Hellwig 1023626738bSChristoph Hellwig /* vr8 - vr11: higher 4 bits of each byte of (Q + Qxy) */ 1033626738bSChristoph Hellwig asm volatile("vsrli.b $vr8, $vr4, 4"); 1043626738bSChristoph Hellwig asm volatile("vsrli.b $vr9, $vr5, 4"); 1053626738bSChristoph Hellwig asm volatile("vsrli.b $vr10, $vr6, 4"); 1063626738bSChristoph Hellwig asm volatile("vsrli.b $vr11, $vr7, 4"); 1073626738bSChristoph Hellwig /* vr4 - vr7: lower 4 bits of each byte of (Q + Qxy) */ 1083626738bSChristoph Hellwig asm volatile("vandi.b $vr4, $vr4, 0x0f"); 1093626738bSChristoph Hellwig asm volatile("vandi.b $vr5, $vr5, 0x0f"); 1103626738bSChristoph Hellwig asm volatile("vandi.b $vr6, $vr6, 0x0f"); 1113626738bSChristoph Hellwig asm volatile("vandi.b $vr7, $vr7, 0x0f"); 1123626738bSChristoph Hellwig /* lookup from qmul[0] */ 1133626738bSChristoph Hellwig asm volatile("vshuf.b $vr4, $vr20, $vr20, $vr4"); 1143626738bSChristoph Hellwig asm volatile("vshuf.b $vr5, $vr20, $vr20, $vr5"); 1153626738bSChristoph Hellwig asm volatile("vshuf.b $vr6, $vr20, $vr20, $vr6"); 1163626738bSChristoph Hellwig asm volatile("vshuf.b $vr7, $vr20, $vr20, $vr7"); 1173626738bSChristoph Hellwig /* lookup from qmul[16] */ 1183626738bSChristoph Hellwig asm volatile("vshuf.b $vr8, $vr21, $vr21, $vr8"); 1193626738bSChristoph Hellwig asm volatile("vshuf.b $vr9, $vr21, $vr21, $vr9"); 1203626738bSChristoph Hellwig asm volatile("vshuf.b $vr10, $vr21, $vr21, $vr10"); 1213626738bSChristoph Hellwig asm volatile("vshuf.b $vr11, $vr21, $vr21, $vr11"); 1223626738bSChristoph Hellwig /* vr16 - vr19: B(Q + Qxy) */ 1233626738bSChristoph Hellwig asm volatile("vxor.v $vr16, $vr8, $vr4"); 1243626738bSChristoph Hellwig asm volatile("vxor.v $vr17, $vr9, $vr5"); 1253626738bSChristoph Hellwig asm volatile("vxor.v $vr18, $vr10, $vr6"); 1263626738bSChristoph Hellwig asm volatile("vxor.v $vr19, $vr11, $vr7"); 1273626738bSChristoph Hellwig 1283626738bSChristoph Hellwig /* vr4 - vr7: higher 4 bits of each byte of (P + Pxy) */ 1293626738bSChristoph Hellwig asm volatile("vsrli.b $vr4, $vr0, 4"); 1303626738bSChristoph Hellwig asm volatile("vsrli.b $vr5, $vr1, 4"); 1313626738bSChristoph Hellwig asm volatile("vsrli.b $vr6, $vr2, 4"); 1323626738bSChristoph Hellwig asm volatile("vsrli.b $vr7, $vr3, 4"); 1333626738bSChristoph Hellwig /* vr12 - vr15: lower 4 bits of each byte of (P + Pxy) */ 1343626738bSChristoph Hellwig asm volatile("vandi.b $vr12, $vr0, 0x0f"); 1353626738bSChristoph Hellwig asm volatile("vandi.b $vr13, $vr1, 0x0f"); 1363626738bSChristoph Hellwig asm volatile("vandi.b $vr14, $vr2, 0x0f"); 1373626738bSChristoph Hellwig asm volatile("vandi.b $vr15, $vr3, 0x0f"); 1383626738bSChristoph Hellwig /* lookup from pbmul[0] */ 1393626738bSChristoph Hellwig asm volatile("vshuf.b $vr12, $vr22, $vr22, $vr12"); 1403626738bSChristoph Hellwig asm volatile("vshuf.b $vr13, $vr22, $vr22, $vr13"); 1413626738bSChristoph Hellwig asm volatile("vshuf.b $vr14, $vr22, $vr22, $vr14"); 1423626738bSChristoph Hellwig asm volatile("vshuf.b $vr15, $vr22, $vr22, $vr15"); 1433626738bSChristoph Hellwig /* lookup from pbmul[16] */ 1443626738bSChristoph Hellwig asm volatile("vshuf.b $vr4, $vr23, $vr23, $vr4"); 1453626738bSChristoph Hellwig asm volatile("vshuf.b $vr5, $vr23, $vr23, $vr5"); 1463626738bSChristoph Hellwig asm volatile("vshuf.b $vr6, $vr23, $vr23, $vr6"); 1473626738bSChristoph Hellwig asm volatile("vshuf.b $vr7, $vr23, $vr23, $vr7"); 1483626738bSChristoph Hellwig /* vr4 - vr7: A(P + Pxy) */ 1493626738bSChristoph Hellwig asm volatile("vxor.v $vr4, $vr4, $vr12"); 1503626738bSChristoph Hellwig asm volatile("vxor.v $vr5, $vr5, $vr13"); 1513626738bSChristoph Hellwig asm volatile("vxor.v $vr6, $vr6, $vr14"); 1523626738bSChristoph Hellwig asm volatile("vxor.v $vr7, $vr7, $vr15"); 1533626738bSChristoph Hellwig 1543626738bSChristoph Hellwig /* vr4 - vr7: A(P + Pxy) + B(Q + Qxy) = Dx */ 1553626738bSChristoph Hellwig asm volatile("vxor.v $vr4, $vr4, $vr16"); 1563626738bSChristoph Hellwig asm volatile("vxor.v $vr5, $vr5, $vr17"); 1573626738bSChristoph Hellwig asm volatile("vxor.v $vr6, $vr6, $vr18"); 1583626738bSChristoph Hellwig asm volatile("vxor.v $vr7, $vr7, $vr19"); 1593626738bSChristoph Hellwig asm volatile("vst $vr4, %0" : "=m" (dq[0])); 1603626738bSChristoph Hellwig asm volatile("vst $vr5, %0" : "=m" (dq[16])); 1613626738bSChristoph Hellwig asm volatile("vst $vr6, %0" : "=m" (dq[32])); 1623626738bSChristoph Hellwig asm volatile("vst $vr7, %0" : "=m" (dq[48])); 1633626738bSChristoph Hellwig 1643626738bSChristoph Hellwig /* vr0 - vr3: P + Pxy + Dx = Dy */ 1653626738bSChristoph Hellwig asm volatile("vxor.v $vr0, $vr0, $vr4"); 1663626738bSChristoph Hellwig asm volatile("vxor.v $vr1, $vr1, $vr5"); 1673626738bSChristoph Hellwig asm volatile("vxor.v $vr2, $vr2, $vr6"); 1683626738bSChristoph Hellwig asm volatile("vxor.v $vr3, $vr3, $vr7"); 1693626738bSChristoph Hellwig asm volatile("vst $vr0, %0" : "=m" (dp[0])); 1703626738bSChristoph Hellwig asm volatile("vst $vr1, %0" : "=m" (dp[16])); 1713626738bSChristoph Hellwig asm volatile("vst $vr2, %0" : "=m" (dp[32])); 1723626738bSChristoph Hellwig asm volatile("vst $vr3, %0" : "=m" (dp[48])); 1733626738bSChristoph Hellwig 1743626738bSChristoph Hellwig bytes -= 64; 1753626738bSChristoph Hellwig p += 64; 1763626738bSChristoph Hellwig q += 64; 1773626738bSChristoph Hellwig dp += 64; 1783626738bSChristoph Hellwig dq += 64; 1793626738bSChristoph Hellwig } 1803626738bSChristoph Hellwig 1813626738bSChristoph Hellwig kernel_fpu_end(); 1823626738bSChristoph Hellwig } 1833626738bSChristoph Hellwig 1843626738bSChristoph Hellwig static void raid6_datap_recov_lsx(int disks, size_t bytes, int faila, 1853626738bSChristoph Hellwig void **ptrs) 1863626738bSChristoph Hellwig { 1873626738bSChristoph Hellwig u8 *p, *q, *dq; 1883626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table */ 1893626738bSChristoph Hellwig 1903626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 1913626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 1923626738bSChristoph Hellwig 1933626738bSChristoph Hellwig /* 1943626738bSChristoph Hellwig * Compute syndrome with zero for the missing data page 1953626738bSChristoph Hellwig * Use the dead data page as temporary storage for delta q 1963626738bSChristoph Hellwig */ 1973626738bSChristoph Hellwig dq = (u8 *)ptrs[faila]; 198885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 1993626738bSChristoph Hellwig ptrs[disks - 1] = dq; 2003626738bSChristoph Hellwig 20135472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 2023626738bSChristoph Hellwig 2033626738bSChristoph Hellwig /* Restore pointer table */ 2043626738bSChristoph Hellwig ptrs[faila] = dq; 2053626738bSChristoph Hellwig ptrs[disks - 1] = q; 2063626738bSChristoph Hellwig 2073626738bSChristoph Hellwig /* Now, pick the proper data tables */ 2083626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]]; 2093626738bSChristoph Hellwig 2103626738bSChristoph Hellwig kernel_fpu_begin(); 2113626738bSChristoph Hellwig 2123626738bSChristoph Hellwig /* vr22, vr23: qmul */ 2133626738bSChristoph Hellwig asm volatile("vld $vr22, %0" : : "m" (qmul[0])); 2143626738bSChristoph Hellwig asm volatile("vld $vr23, %0" : : "m" (qmul[16])); 2153626738bSChristoph Hellwig 2163626738bSChristoph Hellwig while (bytes) { 2173626738bSChristoph Hellwig /* vr0 - vr3: P + Dx */ 2183626738bSChristoph Hellwig asm volatile("vld $vr0, %0" : : "m" (p[0])); 2193626738bSChristoph Hellwig asm volatile("vld $vr1, %0" : : "m" (p[16])); 2203626738bSChristoph Hellwig asm volatile("vld $vr2, %0" : : "m" (p[32])); 2213626738bSChristoph Hellwig asm volatile("vld $vr3, %0" : : "m" (p[48])); 2223626738bSChristoph Hellwig /* vr4 - vr7: Qx */ 2233626738bSChristoph Hellwig asm volatile("vld $vr4, %0" : : "m" (dq[0])); 2243626738bSChristoph Hellwig asm volatile("vld $vr5, %0" : : "m" (dq[16])); 2253626738bSChristoph Hellwig asm volatile("vld $vr6, %0" : : "m" (dq[32])); 2263626738bSChristoph Hellwig asm volatile("vld $vr7, %0" : : "m" (dq[48])); 2273626738bSChristoph Hellwig /* vr4 - vr7: Q + Qx */ 2283626738bSChristoph Hellwig asm volatile("vld $vr8, %0" : : "m" (q[0])); 2293626738bSChristoph Hellwig asm volatile("vld $vr9, %0" : : "m" (q[16])); 2303626738bSChristoph Hellwig asm volatile("vld $vr10, %0" : : "m" (q[32])); 2313626738bSChristoph Hellwig asm volatile("vld $vr11, %0" : : "m" (q[48])); 2323626738bSChristoph Hellwig asm volatile("vxor.v $vr4, $vr4, $vr8"); 2333626738bSChristoph Hellwig asm volatile("vxor.v $vr5, $vr5, $vr9"); 2343626738bSChristoph Hellwig asm volatile("vxor.v $vr6, $vr6, $vr10"); 2353626738bSChristoph Hellwig asm volatile("vxor.v $vr7, $vr7, $vr11"); 2363626738bSChristoph Hellwig 2373626738bSChristoph Hellwig /* vr8 - vr11: higher 4 bits of each byte of (Q + Qx) */ 2383626738bSChristoph Hellwig asm volatile("vsrli.b $vr8, $vr4, 4"); 2393626738bSChristoph Hellwig asm volatile("vsrli.b $vr9, $vr5, 4"); 2403626738bSChristoph Hellwig asm volatile("vsrli.b $vr10, $vr6, 4"); 2413626738bSChristoph Hellwig asm volatile("vsrli.b $vr11, $vr7, 4"); 2423626738bSChristoph Hellwig /* vr4 - vr7: lower 4 bits of each byte of (Q + Qx) */ 2433626738bSChristoph Hellwig asm volatile("vandi.b $vr4, $vr4, 0x0f"); 2443626738bSChristoph Hellwig asm volatile("vandi.b $vr5, $vr5, 0x0f"); 2453626738bSChristoph Hellwig asm volatile("vandi.b $vr6, $vr6, 0x0f"); 2463626738bSChristoph Hellwig asm volatile("vandi.b $vr7, $vr7, 0x0f"); 2473626738bSChristoph Hellwig /* lookup from qmul[0] */ 2483626738bSChristoph Hellwig asm volatile("vshuf.b $vr4, $vr22, $vr22, $vr4"); 2493626738bSChristoph Hellwig asm volatile("vshuf.b $vr5, $vr22, $vr22, $vr5"); 2503626738bSChristoph Hellwig asm volatile("vshuf.b $vr6, $vr22, $vr22, $vr6"); 2513626738bSChristoph Hellwig asm volatile("vshuf.b $vr7, $vr22, $vr22, $vr7"); 2523626738bSChristoph Hellwig /* lookup from qmul[16] */ 2533626738bSChristoph Hellwig asm volatile("vshuf.b $vr8, $vr23, $vr23, $vr8"); 2543626738bSChristoph Hellwig asm volatile("vshuf.b $vr9, $vr23, $vr23, $vr9"); 2553626738bSChristoph Hellwig asm volatile("vshuf.b $vr10, $vr23, $vr23, $vr10"); 2563626738bSChristoph Hellwig asm volatile("vshuf.b $vr11, $vr23, $vr23, $vr11"); 2573626738bSChristoph Hellwig /* vr4 - vr7: qmul(Q + Qx) = Dx */ 2583626738bSChristoph Hellwig asm volatile("vxor.v $vr4, $vr4, $vr8"); 2593626738bSChristoph Hellwig asm volatile("vxor.v $vr5, $vr5, $vr9"); 2603626738bSChristoph Hellwig asm volatile("vxor.v $vr6, $vr6, $vr10"); 2613626738bSChristoph Hellwig asm volatile("vxor.v $vr7, $vr7, $vr11"); 2623626738bSChristoph Hellwig asm volatile("vst $vr4, %0" : "=m" (dq[0])); 2633626738bSChristoph Hellwig asm volatile("vst $vr5, %0" : "=m" (dq[16])); 2643626738bSChristoph Hellwig asm volatile("vst $vr6, %0" : "=m" (dq[32])); 2653626738bSChristoph Hellwig asm volatile("vst $vr7, %0" : "=m" (dq[48])); 2663626738bSChristoph Hellwig 2673626738bSChristoph Hellwig /* vr0 - vr3: P + Dx + Dx = P */ 2683626738bSChristoph Hellwig asm volatile("vxor.v $vr0, $vr0, $vr4"); 2693626738bSChristoph Hellwig asm volatile("vxor.v $vr1, $vr1, $vr5"); 2703626738bSChristoph Hellwig asm volatile("vxor.v $vr2, $vr2, $vr6"); 2713626738bSChristoph Hellwig asm volatile("vxor.v $vr3, $vr3, $vr7"); 2723626738bSChristoph Hellwig asm volatile("vst $vr0, %0" : "=m" (p[0])); 2733626738bSChristoph Hellwig asm volatile("vst $vr1, %0" : "=m" (p[16])); 2743626738bSChristoph Hellwig asm volatile("vst $vr2, %0" : "=m" (p[32])); 2753626738bSChristoph Hellwig asm volatile("vst $vr3, %0" : "=m" (p[48])); 2763626738bSChristoph Hellwig 2773626738bSChristoph Hellwig bytes -= 64; 2783626738bSChristoph Hellwig p += 64; 2793626738bSChristoph Hellwig q += 64; 2803626738bSChristoph Hellwig dq += 64; 2813626738bSChristoph Hellwig } 2823626738bSChristoph Hellwig 2833626738bSChristoph Hellwig kernel_fpu_end(); 2843626738bSChristoph Hellwig } 2853626738bSChristoph Hellwig 2863626738bSChristoph Hellwig const struct raid6_recov_calls raid6_recov_lsx = { 2873626738bSChristoph Hellwig .data2 = raid6_2data_recov_lsx, 2883626738bSChristoph Hellwig .datap = raid6_datap_recov_lsx, 2893626738bSChristoph Hellwig .name = "lsx", 2903626738bSChristoph Hellwig }; 2913626738bSChristoph Hellwig #endif /* CONFIG_CPU_HAS_LSX */ 2923626738bSChristoph Hellwig 2933626738bSChristoph Hellwig #ifdef CONFIG_CPU_HAS_LASX 2943626738bSChristoph Hellwig static void raid6_2data_recov_lasx(int disks, size_t bytes, int faila, 2953626738bSChristoph Hellwig int failb, void **ptrs) 2963626738bSChristoph Hellwig { 2973626738bSChristoph Hellwig u8 *p, *q, *dp, *dq; 2983626738bSChristoph Hellwig const u8 *pbmul; /* P multiplier table for B data */ 2993626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table (for both) */ 3003626738bSChristoph Hellwig 3013626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 3023626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 3033626738bSChristoph Hellwig 3043626738bSChristoph Hellwig /* 3053626738bSChristoph Hellwig * Compute syndrome with zero for the missing data pages 3063626738bSChristoph Hellwig * Use the dead data pages as temporary storage for 3073626738bSChristoph Hellwig * delta p and delta q 3083626738bSChristoph Hellwig */ 3093626738bSChristoph Hellwig dp = (u8 *)ptrs[faila]; 310885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 3113626738bSChristoph Hellwig ptrs[disks - 2] = dp; 3123626738bSChristoph Hellwig dq = (u8 *)ptrs[failb]; 313885d3142SChristoph Hellwig ptrs[failb] = page_address(ZERO_PAGE(0)); 3143626738bSChristoph Hellwig ptrs[disks - 1] = dq; 3153626738bSChristoph Hellwig 31635472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 3173626738bSChristoph Hellwig 3183626738bSChristoph Hellwig /* Restore pointer table */ 3193626738bSChristoph Hellwig ptrs[faila] = dp; 3203626738bSChristoph Hellwig ptrs[failb] = dq; 3213626738bSChristoph Hellwig ptrs[disks - 2] = p; 3223626738bSChristoph Hellwig ptrs[disks - 1] = q; 3233626738bSChristoph Hellwig 3243626738bSChristoph Hellwig /* Now, pick the proper data tables */ 3253626738bSChristoph Hellwig pbmul = raid6_vgfmul[raid6_gfexi[failb - faila]]; 3263626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila] ^ raid6_gfexp[failb]]]; 3273626738bSChristoph Hellwig 3283626738bSChristoph Hellwig kernel_fpu_begin(); 3293626738bSChristoph Hellwig 3303626738bSChristoph Hellwig /* 3313626738bSChristoph Hellwig * xr20, xr21: qmul 3323626738bSChristoph Hellwig * xr22, xr23: pbmul 3333626738bSChristoph Hellwig */ 3343626738bSChristoph Hellwig asm volatile("vld $vr20, %0" : : "m" (qmul[0])); 3353626738bSChristoph Hellwig asm volatile("vld $vr21, %0" : : "m" (qmul[16])); 3363626738bSChristoph Hellwig asm volatile("vld $vr22, %0" : : "m" (pbmul[0])); 3373626738bSChristoph Hellwig asm volatile("vld $vr23, %0" : : "m" (pbmul[16])); 3383626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr20, $xr20"); 3393626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr21, $xr21"); 3403626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr22, $xr22"); 3413626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr23, $xr23"); 3423626738bSChristoph Hellwig 3433626738bSChristoph Hellwig while (bytes) { 3443626738bSChristoph Hellwig /* xr0, xr1: Q */ 3453626738bSChristoph Hellwig asm volatile("xvld $xr0, %0" : : "m" (q[0])); 3463626738bSChristoph Hellwig asm volatile("xvld $xr1, %0" : : "m" (q[32])); 3473626738bSChristoph Hellwig /* xr0, xr1: Q + Qxy */ 3483626738bSChristoph Hellwig asm volatile("xvld $xr4, %0" : : "m" (dq[0])); 3493626738bSChristoph Hellwig asm volatile("xvld $xr5, %0" : : "m" (dq[32])); 3503626738bSChristoph Hellwig asm volatile("xvxor.v $xr0, $xr0, $xr4"); 3513626738bSChristoph Hellwig asm volatile("xvxor.v $xr1, $xr1, $xr5"); 3523626738bSChristoph Hellwig /* xr2, xr3: P */ 3533626738bSChristoph Hellwig asm volatile("xvld $xr2, %0" : : "m" (p[0])); 3543626738bSChristoph Hellwig asm volatile("xvld $xr3, %0" : : "m" (p[32])); 3553626738bSChristoph Hellwig /* xr2, xr3: P + Pxy */ 3563626738bSChristoph Hellwig asm volatile("xvld $xr4, %0" : : "m" (dp[0])); 3573626738bSChristoph Hellwig asm volatile("xvld $xr5, %0" : : "m" (dp[32])); 3583626738bSChristoph Hellwig asm volatile("xvxor.v $xr2, $xr2, $xr4"); 3593626738bSChristoph Hellwig asm volatile("xvxor.v $xr3, $xr3, $xr5"); 3603626738bSChristoph Hellwig 3613626738bSChristoph Hellwig /* xr4, xr5: higher 4 bits of each byte of (Q + Qxy) */ 3623626738bSChristoph Hellwig asm volatile("xvsrli.b $xr4, $xr0, 4"); 3633626738bSChristoph Hellwig asm volatile("xvsrli.b $xr5, $xr1, 4"); 3643626738bSChristoph Hellwig /* xr0, xr1: lower 4 bits of each byte of (Q + Qxy) */ 3653626738bSChristoph Hellwig asm volatile("xvandi.b $xr0, $xr0, 0x0f"); 3663626738bSChristoph Hellwig asm volatile("xvandi.b $xr1, $xr1, 0x0f"); 3673626738bSChristoph Hellwig /* lookup from qmul[0] */ 3683626738bSChristoph Hellwig asm volatile("xvshuf.b $xr0, $xr20, $xr20, $xr0"); 3693626738bSChristoph Hellwig asm volatile("xvshuf.b $xr1, $xr20, $xr20, $xr1"); 3703626738bSChristoph Hellwig /* lookup from qmul[16] */ 3713626738bSChristoph Hellwig asm volatile("xvshuf.b $xr4, $xr21, $xr21, $xr4"); 3723626738bSChristoph Hellwig asm volatile("xvshuf.b $xr5, $xr21, $xr21, $xr5"); 3733626738bSChristoph Hellwig /* xr6, xr7: B(Q + Qxy) */ 3743626738bSChristoph Hellwig asm volatile("xvxor.v $xr6, $xr4, $xr0"); 3753626738bSChristoph Hellwig asm volatile("xvxor.v $xr7, $xr5, $xr1"); 3763626738bSChristoph Hellwig 3773626738bSChristoph Hellwig /* xr4, xr5: higher 4 bits of each byte of (P + Pxy) */ 3783626738bSChristoph Hellwig asm volatile("xvsrli.b $xr4, $xr2, 4"); 3793626738bSChristoph Hellwig asm volatile("xvsrli.b $xr5, $xr3, 4"); 3803626738bSChristoph Hellwig /* xr0, xr1: lower 4 bits of each byte of (P + Pxy) */ 3813626738bSChristoph Hellwig asm volatile("xvandi.b $xr0, $xr2, 0x0f"); 3823626738bSChristoph Hellwig asm volatile("xvandi.b $xr1, $xr3, 0x0f"); 3833626738bSChristoph Hellwig /* lookup from pbmul[0] */ 3843626738bSChristoph Hellwig asm volatile("xvshuf.b $xr0, $xr22, $xr22, $xr0"); 3853626738bSChristoph Hellwig asm volatile("xvshuf.b $xr1, $xr22, $xr22, $xr1"); 3863626738bSChristoph Hellwig /* lookup from pbmul[16] */ 3873626738bSChristoph Hellwig asm volatile("xvshuf.b $xr4, $xr23, $xr23, $xr4"); 3883626738bSChristoph Hellwig asm volatile("xvshuf.b $xr5, $xr23, $xr23, $xr5"); 3893626738bSChristoph Hellwig /* xr0, xr1: A(P + Pxy) */ 3903626738bSChristoph Hellwig asm volatile("xvxor.v $xr0, $xr0, $xr4"); 3913626738bSChristoph Hellwig asm volatile("xvxor.v $xr1, $xr1, $xr5"); 3923626738bSChristoph Hellwig 3933626738bSChristoph Hellwig /* xr0, xr1: A(P + Pxy) + B(Q + Qxy) = Dx */ 3943626738bSChristoph Hellwig asm volatile("xvxor.v $xr0, $xr0, $xr6"); 3953626738bSChristoph Hellwig asm volatile("xvxor.v $xr1, $xr1, $xr7"); 3963626738bSChristoph Hellwig 3973626738bSChristoph Hellwig /* xr2, xr3: P + Pxy + Dx = Dy */ 3983626738bSChristoph Hellwig asm volatile("xvxor.v $xr2, $xr2, $xr0"); 3993626738bSChristoph Hellwig asm volatile("xvxor.v $xr3, $xr3, $xr1"); 4003626738bSChristoph Hellwig 4013626738bSChristoph Hellwig asm volatile("xvst $xr0, %0" : "=m" (dq[0])); 4023626738bSChristoph Hellwig asm volatile("xvst $xr1, %0" : "=m" (dq[32])); 4033626738bSChristoph Hellwig asm volatile("xvst $xr2, %0" : "=m" (dp[0])); 4043626738bSChristoph Hellwig asm volatile("xvst $xr3, %0" : "=m" (dp[32])); 4053626738bSChristoph Hellwig 4063626738bSChristoph Hellwig bytes -= 64; 4073626738bSChristoph Hellwig p += 64; 4083626738bSChristoph Hellwig q += 64; 4093626738bSChristoph Hellwig dp += 64; 4103626738bSChristoph Hellwig dq += 64; 4113626738bSChristoph Hellwig } 4123626738bSChristoph Hellwig 4133626738bSChristoph Hellwig kernel_fpu_end(); 4143626738bSChristoph Hellwig } 4153626738bSChristoph Hellwig 4163626738bSChristoph Hellwig static void raid6_datap_recov_lasx(int disks, size_t bytes, int faila, 4173626738bSChristoph Hellwig void **ptrs) 4183626738bSChristoph Hellwig { 4193626738bSChristoph Hellwig u8 *p, *q, *dq; 4203626738bSChristoph Hellwig const u8 *qmul; /* Q multiplier table */ 4213626738bSChristoph Hellwig 4223626738bSChristoph Hellwig p = (u8 *)ptrs[disks - 2]; 4233626738bSChristoph Hellwig q = (u8 *)ptrs[disks - 1]; 4243626738bSChristoph Hellwig 4253626738bSChristoph Hellwig /* 4263626738bSChristoph Hellwig * Compute syndrome with zero for the missing data page 4273626738bSChristoph Hellwig * Use the dead data page as temporary storage for delta q 4283626738bSChristoph Hellwig */ 4293626738bSChristoph Hellwig dq = (u8 *)ptrs[faila]; 430885d3142SChristoph Hellwig ptrs[faila] = page_address(ZERO_PAGE(0)); 4313626738bSChristoph Hellwig ptrs[disks - 1] = dq; 4323626738bSChristoph Hellwig 43335472bc6SChristoph Hellwig raid6_gen_syndrome(disks, bytes, ptrs); 4343626738bSChristoph Hellwig 4353626738bSChristoph Hellwig /* Restore pointer table */ 4363626738bSChristoph Hellwig ptrs[faila] = dq; 4373626738bSChristoph Hellwig ptrs[disks - 1] = q; 4383626738bSChristoph Hellwig 4393626738bSChristoph Hellwig /* Now, pick the proper data tables */ 4403626738bSChristoph Hellwig qmul = raid6_vgfmul[raid6_gfinv[raid6_gfexp[faila]]]; 4413626738bSChristoph Hellwig 4423626738bSChristoph Hellwig kernel_fpu_begin(); 4433626738bSChristoph Hellwig 4443626738bSChristoph Hellwig /* xr22, xr23: qmul */ 4453626738bSChristoph Hellwig asm volatile("vld $vr22, %0" : : "m" (qmul[0])); 4463626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr22, $xr22"); 4473626738bSChristoph Hellwig asm volatile("vld $vr23, %0" : : "m" (qmul[16])); 4483626738bSChristoph Hellwig asm volatile("xvreplve0.q $xr23, $xr23"); 4493626738bSChristoph Hellwig 4503626738bSChristoph Hellwig while (bytes) { 4513626738bSChristoph Hellwig /* xr0, xr1: P + Dx */ 4523626738bSChristoph Hellwig asm volatile("xvld $xr0, %0" : : "m" (p[0])); 4533626738bSChristoph Hellwig asm volatile("xvld $xr1, %0" : : "m" (p[32])); 4543626738bSChristoph Hellwig /* xr2, xr3: Qx */ 4553626738bSChristoph Hellwig asm volatile("xvld $xr2, %0" : : "m" (dq[0])); 4563626738bSChristoph Hellwig asm volatile("xvld $xr3, %0" : : "m" (dq[32])); 4573626738bSChristoph Hellwig /* xr2, xr3: Q + Qx */ 4583626738bSChristoph Hellwig asm volatile("xvld $xr4, %0" : : "m" (q[0])); 4593626738bSChristoph Hellwig asm volatile("xvld $xr5, %0" : : "m" (q[32])); 4603626738bSChristoph Hellwig asm volatile("xvxor.v $xr2, $xr2, $xr4"); 4613626738bSChristoph Hellwig asm volatile("xvxor.v $xr3, $xr3, $xr5"); 4623626738bSChristoph Hellwig 4633626738bSChristoph Hellwig /* xr4, xr5: higher 4 bits of each byte of (Q + Qx) */ 4643626738bSChristoph Hellwig asm volatile("xvsrli.b $xr4, $xr2, 4"); 4653626738bSChristoph Hellwig asm volatile("xvsrli.b $xr5, $xr3, 4"); 4663626738bSChristoph Hellwig /* xr2, xr3: lower 4 bits of each byte of (Q + Qx) */ 4673626738bSChristoph Hellwig asm volatile("xvandi.b $xr2, $xr2, 0x0f"); 4683626738bSChristoph Hellwig asm volatile("xvandi.b $xr3, $xr3, 0x0f"); 4693626738bSChristoph Hellwig /* lookup from qmul[0] */ 4703626738bSChristoph Hellwig asm volatile("xvshuf.b $xr2, $xr22, $xr22, $xr2"); 4713626738bSChristoph Hellwig asm volatile("xvshuf.b $xr3, $xr22, $xr22, $xr3"); 4723626738bSChristoph Hellwig /* lookup from qmul[16] */ 4733626738bSChristoph Hellwig asm volatile("xvshuf.b $xr4, $xr23, $xr23, $xr4"); 4743626738bSChristoph Hellwig asm volatile("xvshuf.b $xr5, $xr23, $xr23, $xr5"); 4753626738bSChristoph Hellwig /* xr2, xr3: qmul(Q + Qx) = Dx */ 4763626738bSChristoph Hellwig asm volatile("xvxor.v $xr2, $xr2, $xr4"); 4773626738bSChristoph Hellwig asm volatile("xvxor.v $xr3, $xr3, $xr5"); 4783626738bSChristoph Hellwig 4793626738bSChristoph Hellwig /* xr0, xr1: P + Dx + Dx = P */ 4803626738bSChristoph Hellwig asm volatile("xvxor.v $xr0, $xr0, $xr2"); 4813626738bSChristoph Hellwig asm volatile("xvxor.v $xr1, $xr1, $xr3"); 4823626738bSChristoph Hellwig 4833626738bSChristoph Hellwig asm volatile("xvst $xr2, %0" : "=m" (dq[0])); 4843626738bSChristoph Hellwig asm volatile("xvst $xr3, %0" : "=m" (dq[32])); 4853626738bSChristoph Hellwig asm volatile("xvst $xr0, %0" : "=m" (p[0])); 4863626738bSChristoph Hellwig asm volatile("xvst $xr1, %0" : "=m" (p[32])); 4873626738bSChristoph Hellwig 4883626738bSChristoph Hellwig bytes -= 64; 4893626738bSChristoph Hellwig p += 64; 4903626738bSChristoph Hellwig q += 64; 4913626738bSChristoph Hellwig dq += 64; 4923626738bSChristoph Hellwig } 4933626738bSChristoph Hellwig 4943626738bSChristoph Hellwig kernel_fpu_end(); 4953626738bSChristoph Hellwig } 4963626738bSChristoph Hellwig 4973626738bSChristoph Hellwig const struct raid6_recov_calls raid6_recov_lasx = { 4983626738bSChristoph Hellwig .data2 = raid6_2data_recov_lasx, 4993626738bSChristoph Hellwig .datap = raid6_datap_recov_lasx, 5003626738bSChristoph Hellwig .name = "lasx", 5013626738bSChristoph Hellwig }; 5023626738bSChristoph Hellwig #endif /* CONFIG_CPU_HAS_LASX */ 503