2005-04-17 02:20:36 +04:00
/ * - * - l i n u x - c - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
*
* Copyright 2002 - 2004 H . Peter Anvin - All Rights Reserved
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , Inc . , 53 Temple Place Ste 330 ,
2009-03-31 07:57:37 +04:00
* Boston MA 02111 - 1307 , USA ; either version 2 of the License , or
2005-04-17 02:20:36 +04:00
* ( at your option ) any later version ; incorporated herein by reference .
*
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
/ *
* raid6altivec$ # . c
*
* $ # - way unrolled portable integer math RAID - 6 instruction set
*
2009-10-16 09:25:19 +04:00
* This file is postprocessed using unroll . awk
2005-04-17 02:20:36 +04:00
*
* < benh > hpa : in process ,
* you can just "steal" the vec unit with enable _kernel _altivec ( ) ( but
* bracked this with preempt _disable / enable or in a lock )
* /
2009-03-31 08:09:39 +04:00
# include < linux / raid / pq . h >
2005-04-17 02:20:36 +04:00
# ifdef CONFIG _ALTIVEC
# include < altivec . h >
2005-09-17 06:27:29 +04:00
# ifdef _ _KERNEL _ _
# include < asm / system . h >
# include < asm / cputable . h >
# endif
2005-04-17 02:20:36 +04:00
/ *
2005-09-17 06:27:29 +04:00
* This is the C data type to use . We use a vector of
* signed char so vec _cmpgt ( ) will generate the right
* instruction .
2005-04-17 02:20:36 +04:00
* /
2005-09-17 06:27:29 +04:00
typedef vector signed char unative _t ;
2005-04-17 02:20:36 +04:00
2005-09-17 06:27:29 +04:00
# define NBYTES ( x ) ( ( vector signed char ) { x , x , x , x , x , x , x , x , x , x , x , x , x , x , x , x } )
2005-04-17 02:20:36 +04:00
# define NSIZE sizeof ( unative _t )
/ *
* The SHLBYTE ( ) operation shifts each byte left by 1 , * not *
* rolling over into the next byte
* /
static inline _ _attribute _const _ _ unative _t SHLBYTE ( unative _t v )
{
return vec _add ( v , v ) ;
}
/ *
* The MASK ( ) operation returns 0xFF in any byte for which the high
* bit is 1 , 0x00 for any byte for which the high bit is 0.
* /
static inline _ _attribute _const _ _ unative _t MASK ( unative _t v )
{
unative _t zv = NBYTES ( 0 ) ;
/* vec_cmpgt returns a vector bool char; thus the need for the cast */
return ( unative _t ) vec _cmpgt ( zv , v ) ;
}
/ * T h i s i s n o i n l i n e t o m a k e d a m n e d s u r e t h a t g c c d o e s n ' t m o v e a n y o f t h e
Altivec code around the enable / disable code * /
static void noinline
raid6 _altivec$ # _gen _syndrome _real ( int disks , size _t bytes , void * * ptrs )
{
u8 * * dptr = ( u8 * * ) ptrs ;
u8 * p , * q ;
int d , z , z0 ;
unative _t wd$$ , wq$$ , wp$$ , w1$$ , w2$$ ;
unative _t x1d = NBYTES ( 0x1d ) ;
z0 = disks - 3 ; /* Highest data disk */
p = dptr [ z0 + 1 ] ; /* XOR parity */
q = dptr [ z0 + 2 ] ; /* RS syndrome */
for ( d = 0 ; d < bytes ; d += NSIZE * $ # ) {
wq$$ = wp$$ = * ( unative _t * ) & dptr [ z0 ] [ d + $$ * NSIZE ] ;
for ( z = z0 - 1 ; z >= 0 ; z -- ) {
wd$$ = * ( unative _t * ) & dptr [ z ] [ d + $$ * NSIZE ] ;
wp$$ = vec _xor ( wp$$ , wd$$ ) ;
w2$$ = MASK ( wq$$ ) ;
w1$$ = SHLBYTE ( wq$$ ) ;
w2$$ = vec _and ( w2$$ , x1d ) ;
w1$$ = vec _xor ( w1$$ , w2$$ ) ;
wq$$ = vec _xor ( w1$$ , wd$$ ) ;
}
* ( unative _t * ) & p [ d + NSIZE * $$ ] = wp$$ ;
* ( unative _t * ) & q [ d + NSIZE * $$ ] = wq$$ ;
}
}
static void raid6 _altivec$ # _gen _syndrome ( int disks , size _t bytes , void * * ptrs )
{
preempt _disable ( ) ;
enable _kernel _altivec ( ) ;
raid6 _altivec$ # _gen _syndrome _real ( disks , bytes , ptrs ) ;
preempt _enable ( ) ;
}
int raid6 _have _altivec ( void ) ;
# if $ # == 1
int raid6 _have _altivec ( void )
{
/* This assumes either all CPUs have Altivec or none does */
2005-09-17 06:27:29 +04:00
# ifdef _ _KERNEL _ _
2005-04-17 02:20:36 +04:00
return cpu _has _feature ( CPU _FTR _ALTIVEC ) ;
2005-09-17 06:27:29 +04:00
# else
return 1 ;
# endif
2005-04-17 02:20:36 +04:00
}
# endif
const struct raid6 _calls raid6 _altivec$ # = {
raid6 _altivec$ # _gen _syndrome ,
raid6 _have _altivec ,
"altivecx$#" ,
0
} ;
# endif /* CONFIG_ALTIVEC */