1cc4589ebSDavid Woodhouse/* -*- linux-c -*- ------------------------------------------------------- * 2cc4589ebSDavid Woodhouse * 3cc4589ebSDavid Woodhouse * Copyright 2002-2004 H. Peter Anvin - All Rights Reserved 4cc4589ebSDavid Woodhouse * 5cc4589ebSDavid Woodhouse * This program is free software; you can redistribute it and/or modify 6cc4589ebSDavid Woodhouse * it under the terms of the GNU General Public License as published by 7cc4589ebSDavid Woodhouse * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8cc4589ebSDavid Woodhouse * Boston MA 02111-1307, USA; either version 2 of the License, or 9cc4589ebSDavid Woodhouse * (at your option) any later version; incorporated herein by reference. 10cc4589ebSDavid Woodhouse * 11cc4589ebSDavid Woodhouse * ----------------------------------------------------------------------- */ 12cc4589ebSDavid Woodhouse 13cc4589ebSDavid Woodhouse/* 14cc4589ebSDavid Woodhouse * raid6altivec$#.c 15cc4589ebSDavid Woodhouse * 16cc4589ebSDavid Woodhouse * $#-way unrolled portable integer math RAID-6 instruction set 17cc4589ebSDavid Woodhouse * 18cc4589ebSDavid Woodhouse * This file is postprocessed using unroll.awk 19cc4589ebSDavid Woodhouse * 20cc4589ebSDavid Woodhouse * <benh> hpa: in process, 21cc4589ebSDavid Woodhouse * you can just "steal" the vec unit with enable_kernel_altivec() (but 22cc4589ebSDavid Woodhouse * bracked this with preempt_disable/enable or in a lock) 23cc4589ebSDavid Woodhouse */ 24cc4589ebSDavid Woodhouse 25cc4589ebSDavid Woodhouse#include <linux/raid/pq.h> 26cc4589ebSDavid Woodhouse 27*aa9532d4SMatt Brown#ifdef CONFIG_ALTIVEC 28*aa9532d4SMatt Brown 29cc4589ebSDavid Woodhouse#include <altivec.h> 30cc4589ebSDavid Woodhouse#ifdef __KERNEL__ 31cc4589ebSDavid Woodhouse# include <asm/cputable.h> 32ae3a197eSDavid Howells# include <asm/switch_to.h> 33*aa9532d4SMatt Brown#endif /* __KERNEL__ */ 34cc4589ebSDavid Woodhouse 35cc4589ebSDavid Woodhouse/* 36cc4589ebSDavid Woodhouse * This is the C data type to use. We use a vector of 37cc4589ebSDavid Woodhouse * signed char so vec_cmpgt() will generate the right 38cc4589ebSDavid Woodhouse * instruction. 39cc4589ebSDavid Woodhouse */ 40cc4589ebSDavid Woodhouse 41cc4589ebSDavid Woodhousetypedef vector signed char unative_t; 42cc4589ebSDavid Woodhouse 43cc4589ebSDavid Woodhouse#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) 44cc4589ebSDavid Woodhouse#define NSIZE sizeof(unative_t) 45cc4589ebSDavid Woodhouse 46cc4589ebSDavid Woodhouse/* 47cc4589ebSDavid Woodhouse * The SHLBYTE() operation shifts each byte left by 1, *not* 48cc4589ebSDavid Woodhouse * rolling over into the next byte 49cc4589ebSDavid Woodhouse */ 50cc4589ebSDavid Woodhousestatic inline __attribute_const__ unative_t SHLBYTE(unative_t v) 51cc4589ebSDavid Woodhouse{ 52cc4589ebSDavid Woodhouse return vec_add(v,v); 53cc4589ebSDavid Woodhouse} 54cc4589ebSDavid Woodhouse 55cc4589ebSDavid Woodhouse/* 56cc4589ebSDavid Woodhouse * The MASK() operation returns 0xFF in any byte for which the high 57cc4589ebSDavid Woodhouse * bit is 1, 0x00 for any byte for which the high bit is 0. 58cc4589ebSDavid Woodhouse */ 59cc4589ebSDavid Woodhousestatic inline __attribute_const__ unative_t MASK(unative_t v) 60cc4589ebSDavid Woodhouse{ 61cc4589ebSDavid Woodhouse unative_t zv = NBYTES(0); 62cc4589ebSDavid Woodhouse 63cc4589ebSDavid Woodhouse /* vec_cmpgt returns a vector bool char; thus the need for the cast */ 64cc4589ebSDavid Woodhouse return (unative_t)vec_cmpgt(zv, v); 65cc4589ebSDavid Woodhouse} 66cc4589ebSDavid Woodhouse 67cc4589ebSDavid Woodhouse 68cc4589ebSDavid Woodhouse/* This is noinline to make damned sure that gcc doesn't move any of the 69cc4589ebSDavid Woodhouse Altivec code around the enable/disable code */ 70cc4589ebSDavid Woodhousestatic void noinline 71cc4589ebSDavid Woodhouseraid6_altivec$#_gen_syndrome_real(int disks, size_t bytes, void **ptrs) 72cc4589ebSDavid Woodhouse{ 73cc4589ebSDavid Woodhouse u8 **dptr = (u8 **)ptrs; 74cc4589ebSDavid Woodhouse u8 *p, *q; 75cc4589ebSDavid Woodhouse int d, z, z0; 76cc4589ebSDavid Woodhouse 77cc4589ebSDavid Woodhouse unative_t wd$$, wq$$, wp$$, w1$$, w2$$; 78cc4589ebSDavid Woodhouse unative_t x1d = NBYTES(0x1d); 79cc4589ebSDavid Woodhouse 80cc4589ebSDavid Woodhouse z0 = disks - 3; /* Highest data disk */ 81cc4589ebSDavid Woodhouse p = dptr[z0+1]; /* XOR parity */ 82cc4589ebSDavid Woodhouse q = dptr[z0+2]; /* RS syndrome */ 83cc4589ebSDavid Woodhouse 84cc4589ebSDavid Woodhouse for ( d = 0 ; d < bytes ; d += NSIZE*$# ) { 85cc4589ebSDavid Woodhouse wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE]; 86cc4589ebSDavid Woodhouse for ( z = z0-1 ; z >= 0 ; z-- ) { 87cc4589ebSDavid Woodhouse wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE]; 88cc4589ebSDavid Woodhouse wp$$ = vec_xor(wp$$, wd$$); 89cc4589ebSDavid Woodhouse w2$$ = MASK(wq$$); 90cc4589ebSDavid Woodhouse w1$$ = SHLBYTE(wq$$); 91cc4589ebSDavid Woodhouse w2$$ = vec_and(w2$$, x1d); 92cc4589ebSDavid Woodhouse w1$$ = vec_xor(w1$$, w2$$); 93cc4589ebSDavid Woodhouse wq$$ = vec_xor(w1$$, wd$$); 94cc4589ebSDavid Woodhouse } 95cc4589ebSDavid Woodhouse *(unative_t *)&p[d+NSIZE*$$] = wp$$; 96cc4589ebSDavid Woodhouse *(unative_t *)&q[d+NSIZE*$$] = wq$$; 97cc4589ebSDavid Woodhouse } 98cc4589ebSDavid Woodhouse} 99cc4589ebSDavid Woodhouse 100cc4589ebSDavid Woodhousestatic void raid6_altivec$#_gen_syndrome(int disks, size_t bytes, void **ptrs) 101cc4589ebSDavid Woodhouse{ 102cc4589ebSDavid Woodhouse preempt_disable(); 103cc4589ebSDavid Woodhouse enable_kernel_altivec(); 104cc4589ebSDavid Woodhouse 105cc4589ebSDavid Woodhouse raid6_altivec$#_gen_syndrome_real(disks, bytes, ptrs); 106cc4589ebSDavid Woodhouse 107dc4fbba1SAnton Blanchard disable_kernel_altivec(); 108cc4589ebSDavid Woodhouse preempt_enable(); 109cc4589ebSDavid Woodhouse} 110cc4589ebSDavid Woodhouse 111cc4589ebSDavid Woodhouseint raid6_have_altivec(void); 112cc4589ebSDavid Woodhouse#if $# == 1 113cc4589ebSDavid Woodhouseint raid6_have_altivec(void) 114cc4589ebSDavid Woodhouse{ 115cc4589ebSDavid Woodhouse /* This assumes either all CPUs have Altivec or none does */ 116cc4589ebSDavid Woodhouse# ifdef __KERNEL__ 117cc4589ebSDavid Woodhouse return cpu_has_feature(CPU_FTR_ALTIVEC); 118cc4589ebSDavid Woodhouse# else 119cc4589ebSDavid Woodhouse return 1; 120cc4589ebSDavid Woodhouse# endif 121cc4589ebSDavid Woodhouse} 122cc4589ebSDavid Woodhouse#endif 123cc4589ebSDavid Woodhouse 124cc4589ebSDavid Woodhouseconst struct raid6_calls raid6_altivec$# = { 125cc4589ebSDavid Woodhouse raid6_altivec$#_gen_syndrome, 126fe5cbc6eSMarkus Stockhausen NULL, /* XOR not yet implemented */ 127cc4589ebSDavid Woodhouse raid6_have_altivec, 128cc4589ebSDavid Woodhouse "altivecx$#", 129cc4589ebSDavid Woodhouse 0 130cc4589ebSDavid Woodhouse}; 131cc4589ebSDavid Woodhouse 132cc4589ebSDavid Woodhouse#endif /* CONFIG_ALTIVEC */ 133