18c2ecf20Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * Copyright 2002-2004 H. Peter Anvin - All Rights Reserved 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 78c2ecf20Sopenharmony_ci * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 88c2ecf20Sopenharmony_ci * Boston MA 02111-1307, USA; either version 2 of the License, or 98c2ecf20Sopenharmony_ci * (at your option) any later version; incorporated herein by reference. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * ----------------------------------------------------------------------- */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * int$#.c 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * $#-way unrolled portable integer math RAID-6 instruction set 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * This file is postprocessed using unroll.awk 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <linux/raid/pq.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* 248c2ecf20Sopenharmony_ci * This is the C data type to use 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* Change this from BITS_PER_LONG if there is something better... */ 288c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 64 298c2ecf20Sopenharmony_ci# define NBYTES(x) ((x) * 0x0101010101010101UL) 308c2ecf20Sopenharmony_ci# define NSIZE 8 318c2ecf20Sopenharmony_ci# define NSHIFT 3 328c2ecf20Sopenharmony_ci# define NSTRING "64" 338c2ecf20Sopenharmony_citypedef u64 unative_t; 348c2ecf20Sopenharmony_ci#else 358c2ecf20Sopenharmony_ci# define NBYTES(x) ((x) * 0x01010101U) 368c2ecf20Sopenharmony_ci# define NSIZE 4 378c2ecf20Sopenharmony_ci# define NSHIFT 2 388c2ecf20Sopenharmony_ci# define NSTRING "32" 398c2ecf20Sopenharmony_citypedef u32 unative_t; 408c2ecf20Sopenharmony_ci#endif 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * IA-64 wants insane amounts of unrolling. On other architectures that 468c2ecf20Sopenharmony_ci * is just a waste of space. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci#if ($# <= 8) || defined(__ia64__) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* 528c2ecf20Sopenharmony_ci * These sub-operations are separate inlines since they can sometimes be 538c2ecf20Sopenharmony_ci * specially optimized using architecture-specific hacks. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * The SHLBYTE() operation shifts each byte left by 1, *not* 588c2ecf20Sopenharmony_ci * rolling over into the next byte 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_cistatic inline __attribute_const__ unative_t SHLBYTE(unative_t v) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci unative_t vv; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci vv = (v << 1) & NBYTES(0xfe); 658c2ecf20Sopenharmony_ci return vv; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* 698c2ecf20Sopenharmony_ci * The MASK() operation returns 0xFF in any byte for which the high 708c2ecf20Sopenharmony_ci * bit is 1, 0x00 for any byte for which the high bit is 0. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_cistatic inline __attribute_const__ unative_t MASK(unative_t v) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci unative_t vv; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci vv = v & NBYTES(0x80); 778c2ecf20Sopenharmony_ci vv = (vv << 1) - (vv >> 7); /* Overflow on the top bit is OK */ 788c2ecf20Sopenharmony_ci return vv; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic void raid6_int$#_gen_syndrome(int disks, size_t bytes, void **ptrs) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci u8 **dptr = (u8 **)ptrs; 858c2ecf20Sopenharmony_ci u8 *p, *q; 868c2ecf20Sopenharmony_ci int d, z, z0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci unative_t wd$$, wq$$, wp$$, w1$$, w2$$; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci z0 = disks - 3; /* Highest data disk */ 918c2ecf20Sopenharmony_ci p = dptr[z0+1]; /* XOR parity */ 928c2ecf20Sopenharmony_ci q = dptr[z0+2]; /* RS syndrome */ 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci for ( d = 0 ; d < bytes ; d += NSIZE*$# ) { 958c2ecf20Sopenharmony_ci wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; 968c2ecf20Sopenharmony_ci for ( z = z0-1 ; z >= 0 ; z-- ) { 978c2ecf20Sopenharmony_ci wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; 988c2ecf20Sopenharmony_ci wp$$ ^= wd$$; 998c2ecf20Sopenharmony_ci w2$$ = MASK(wq$$); 1008c2ecf20Sopenharmony_ci w1$$ = SHLBYTE(wq$$); 1018c2ecf20Sopenharmony_ci w2$$ &= NBYTES(0x1d); 1028c2ecf20Sopenharmony_ci w1$$ ^= w2$$; 1038c2ecf20Sopenharmony_ci wq$$ = w1$$ ^ wd$$; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci *(unative_t *)&p[d+NSIZE*$$] = wp$$; 1068c2ecf20Sopenharmony_ci *(unative_t *)&q[d+NSIZE*$$] = wq$$; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void raid6_int$#_xor_syndrome(int disks, int start, int stop, 1118c2ecf20Sopenharmony_ci size_t bytes, void **ptrs) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci u8 **dptr = (u8 **)ptrs; 1148c2ecf20Sopenharmony_ci u8 *p, *q; 1158c2ecf20Sopenharmony_ci int d, z, z0; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci unative_t wd$$, wq$$, wp$$, w1$$, w2$$; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci z0 = stop; /* P/Q right side optimization */ 1208c2ecf20Sopenharmony_ci p = dptr[disks-2]; /* XOR parity */ 1218c2ecf20Sopenharmony_ci q = dptr[disks-1]; /* RS syndrome */ 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci for ( d = 0 ; d < bytes ; d += NSIZE*$# ) { 1248c2ecf20Sopenharmony_ci /* P/Q data pages */ 1258c2ecf20Sopenharmony_ci wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; 1268c2ecf20Sopenharmony_ci for ( z = z0-1 ; z >= start ; z-- ) { 1278c2ecf20Sopenharmony_ci wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; 1288c2ecf20Sopenharmony_ci wp$$ ^= wd$$; 1298c2ecf20Sopenharmony_ci w2$$ = MASK(wq$$); 1308c2ecf20Sopenharmony_ci w1$$ = SHLBYTE(wq$$); 1318c2ecf20Sopenharmony_ci w2$$ &= NBYTES(0x1d); 1328c2ecf20Sopenharmony_ci w1$$ ^= w2$$; 1338c2ecf20Sopenharmony_ci wq$$ = w1$$ ^ wd$$; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci /* P/Q left side optimization */ 1368c2ecf20Sopenharmony_ci for ( z = start-1 ; z >= 0 ; z-- ) { 1378c2ecf20Sopenharmony_ci w2$$ = MASK(wq$$); 1388c2ecf20Sopenharmony_ci w1$$ = SHLBYTE(wq$$); 1398c2ecf20Sopenharmony_ci w2$$ &= NBYTES(0x1d); 1408c2ecf20Sopenharmony_ci wq$$ = w1$$ ^ w2$$; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci *(unative_t *)&p[d+NSIZE*$$] ^= wp$$; 1438c2ecf20Sopenharmony_ci *(unative_t *)&q[d+NSIZE*$$] ^= wq$$; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ciconst struct raid6_calls raid6_intx$# = { 1498c2ecf20Sopenharmony_ci raid6_int$#_gen_syndrome, 1508c2ecf20Sopenharmony_ci raid6_int$#_xor_syndrome, 1518c2ecf20Sopenharmony_ci NULL, /* always valid */ 1528c2ecf20Sopenharmony_ci "int" NSTRING "x$#", 1538c2ecf20Sopenharmony_ci 0 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#endif 157