Branch data Line data Source code
1 : : /* -*- linux-c -*- ------------------------------------------------------- *
2 : : *
3 : : * Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
4 : : *
5 : : * This program is free software; you can redistribute it and/or modify
6 : : * it under the terms of the GNU General Public License as published by
7 : : * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 : : * Boston MA 02111-1307, USA; either version 2 of the License, or
9 : : * (at your option) any later version; incorporated herein by reference.
10 : : *
11 : : * ----------------------------------------------------------------------- */
12 : :
13 : : /*
14 : : * int2.c
15 : : *
16 : : * 2-way unrolled portable integer math RAID-6 instruction set
17 : : *
18 : : * This file is postprocessed using unroll.awk
19 : : */
20 : :
21 : : #include <linux/raid/pq.h>
22 : :
23 : : /*
24 : : * This is the C data type to use
25 : : */
26 : :
27 : : /* Change this from BITS_PER_LONG if there is something better... */
28 : : #if BITS_PER_LONG == 64
29 : : # define NBYTES(x) ((x) * 0x0101010101010101UL)
30 : : # define NSIZE 8
31 : : # define NSHIFT 3
32 : : # define NSTRING "64"
33 : : typedef u64 unative_t;
34 : : #else
35 : : # define NBYTES(x) ((x) * 0x01010101U)
36 : : # define NSIZE 4
37 : : # define NSHIFT 2
38 : : # define NSTRING "32"
39 : : typedef u32 unative_t;
40 : : #endif
41 : :
42 : :
43 : :
44 : : /*
45 : : * IA-64 wants insane amounts of unrolling. On other architectures that
46 : : * is just a waste of space.
47 : : */
48 : : #if (2 <= 8) || defined(__ia64__)
49 : :
50 : :
51 : : /*
52 : : * These sub-operations are separate inlines since they can sometimes be
53 : : * specially optimized using architecture-specific hacks.
54 : : */
55 : :
56 : : /*
57 : : * The SHLBYTE() operation shifts each byte left by 1, *not*
58 : : * rolling over into the next byte
59 : : */
60 : : static inline __attribute_const__ unative_t SHLBYTE(unative_t v)
61 : : {
62 : : unative_t vv;
63 : :
64 : 0 : vv = (v << 1) & NBYTES(0xfe);
65 : : return vv;
66 : : }
67 : :
68 : : /*
69 : : * The MASK() operation returns 0xFF in any byte for which the high
70 : : * bit is 1, 0x00 for any byte for which the high bit is 0.
71 : : */
72 : : static inline __attribute_const__ unative_t MASK(unative_t v)
73 : : {
74 : : unative_t vv;
75 : :
76 : 0 : vv = v & NBYTES(0x80);
77 : 0 : vv = (vv << 1) - (vv >> 7); /* Overflow on the top bit is OK */
78 : : return vv;
79 : : }
80 : :
81 : :
82 : 0 : static void raid6_int2_gen_syndrome(int disks, size_t bytes, void **ptrs)
83 : : {
84 : : u8 **dptr = (u8 **)ptrs;
85 : : u8 *p, *q;
86 : : int d, z, z0;
87 : :
88 : : unative_t wd0, wq0, wp0, w10, w20;
89 : : unative_t wd1, wq1, wp1, w11, w21;
90 : :
91 : 0 : z0 = disks - 3; /* Highest data disk */
92 : 0 : p = dptr[z0+1]; /* XOR parity */
93 : 0 : q = dptr[z0+2]; /* RS syndrome */
94 : :
95 [ # # ]: 0 : for ( d = 0 ; d < bytes ; d += NSIZE*2 ) {
96 : 0 : wq0 = wp0 = *(unative_t *)&dptr[z0][d+0*NSIZE];
97 : 0 : wq1 = wp1 = *(unative_t *)&dptr[z0][d+1*NSIZE];
98 [ # # ]: 0 : for ( z = z0-1 ; z >= 0 ; z-- ) {
99 : 0 : wd0 = *(unative_t *)&dptr[z][d+0*NSIZE];
100 : 0 : wd1 = *(unative_t *)&dptr[z][d+1*NSIZE];
101 : 0 : wp0 ^= wd0;
102 : 0 : wp1 ^= wd1;
103 : : w20 = MASK(wq0);
104 : : w21 = MASK(wq1);
105 : : w10 = SHLBYTE(wq0);
106 : : w11 = SHLBYTE(wq1);
107 : 0 : w20 &= NBYTES(0x1d);
108 : 0 : w21 &= NBYTES(0x1d);
109 : 0 : w10 ^= w20;
110 : 0 : w11 ^= w21;
111 : 0 : wq0 = w10 ^ wd0;
112 : 0 : wq1 = w11 ^ wd1;
113 : : }
114 : 0 : *(unative_t *)&p[d+NSIZE*0] = wp0;
115 : 0 : *(unative_t *)&p[d+NSIZE*1] = wp1;
116 : 0 : *(unative_t *)&q[d+NSIZE*0] = wq0;
117 : 0 : *(unative_t *)&q[d+NSIZE*1] = wq1;
118 : : }
119 : 0 : }
120 : :
121 : : const struct raid6_calls raid6_intx2 = {
122 : : raid6_int2_gen_syndrome,
123 : : NULL, /* always valid */
124 : : "int" NSTRING "x2",
125 : : 0
126 : : };
127 : :
128 : : #endif
|