11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -*- linux-c -*- ------------------------------------------------------- * 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 H. Peter Anvin - All Rights Reserved 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 893ed05e2a56b5ee06c0100a169433b11c4aa5d0bAtsushi SAKAI * Boston MA 02111-1307, USA; either version 2 of the License, or 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version; incorporated herein by reference. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ----------------------------------------------------------------------- */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef LINUX_RAID_RAID6_H 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINUX_RAID_RAID6_H 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __KERNEL__ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set to 1 to use kernel-wide empty_zero_page */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAID6_USE_EMPTY_ZERO_PAGE 0 20bff61975b3d6c18ee31457cc5b4d73042f44915fNeilBrown#include <linux/blkdev.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* We need a pre-zeroed page... if we don't want to use the kernel-provided 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds one define it here */ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RAID6_USE_EMPTY_ZERO_PAGE 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define raid6_empty_zero_page empty_zero_page 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const char raid6_empty_zero_page[PAGE_SIZE]; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else /* ! __KERNEL__ */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Used for testing in user space */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <inttypes.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <limits.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stddef.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/mman.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/types.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Not standard, but glibc defines it */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BITS_PER_LONG __WORDSIZE 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef uint8_t u8; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef uint16_t u16; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef uint32_t u32; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef uint64_t u64; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef PAGE_SIZE 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define PAGE_SIZE 4096 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const char raid6_empty_zero_page[PAGE_SIZE]; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __init 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __exit 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __attribute_const__ __attribute__((const)) 56d7e70ba45fd9850296ebb78ff5827f6a375f650cH. Peter Anvin#define noinline __attribute__((noinline)) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define preempt_enable() 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define preempt_disable() 60d7e70ba45fd9850296ebb78ff5827f6a375f650cH. Peter Anvin#define cpu_has_feature(x) 1 61d7e70ba45fd9850296ebb78ff5827f6a375f650cH. Peter Anvin#define enable_kernel_altivec() 62d7e70ba45fd9850296ebb78ff5827f6a375f650cH. Peter Anvin#define disable_kernel_altivec() 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams#define EXPORT_SYMBOL(sym) 65d5302fe41ffb28d0a48be6a71becba36d3453ae0NeilBrown#define EXPORT_SYMBOL_GPL(sym) 66f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams#define MODULE_LICENSE(licence) 67d5302fe41ffb28d0a48be6a71becba36d3453ae0NeilBrown#define MODULE_DESCRIPTION(desc) 68f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams#define subsys_initcall(x) 69f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams#define module_exit(x) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* __KERNEL__ */ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Routine choices */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct raid6_calls { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void (*gen_syndrome)(int, size_t, void **); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int (*valid)(void); /* Returns 1 if this routine set is usable */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *name; /* Name of this routine set */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int prefer; /* Has special performance attribute */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Selected algorithm */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct raid6_calls raid6_call; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 837820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrown/* Various routine sets */ 847820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx1; 857820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx2; 867820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx4; 877820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx8; 887820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx16; 897820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_intx32; 907820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_mmxx1; 917820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_mmxx2; 927820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_sse1x1; 937820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_sse1x2; 947820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_sse2x1; 957820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_sse2x2; 967820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_sse2x4; 977820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_altivec1; 987820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_altivec2; 997820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_altivec4; 1007820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrownextern const struct raid6_calls raid6_altivec8; 1017820f9e1dddcfebae2698fb2a245d04ce3aa6e74NeilBrown 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Algorithm list */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const struct raid6_calls * const raid6_algos[]; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint raid6_select_algo(void); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Return values from chk_syndrome */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAID6_OK 0 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAID6_P_BAD 1 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAID6_Q_BAD 2 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAID6_PQ_BAD 3 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Galois field tables */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const u8 raid6_gfmul[256][256] __attribute__((aligned(256))); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const u8 raid6_gfexp[256] __attribute__((aligned(256))); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const u8 raid6_gfinv[256] __attribute__((aligned(256))); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const u8 raid6_gfexi[256] __attribute__((aligned(256))); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Recovery routines */ 119f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williamsvoid raid6_2data_recov(int disks, size_t bytes, int faila, int failb, 120f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams void **ptrs); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs); 122f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williamsvoid raid6_dual_recov(int disks, size_t bytes, int faila, int failb, 123f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams void **ptrs); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Some definitions to allow code to be compiled for testing in userspace */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef __KERNEL__ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define jiffies raid6_jiffies() 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define printk printf 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define GFP_KERNEL 0 131f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams# define __get_free_pages(x, y) ((unsigned long)mmap(NULL, PAGE_SIZE << (y), \ 132f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams PROT_READ|PROT_WRITE, \ 133f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams MAP_PRIVATE|MAP_ANONYMOUS,\ 134f701d589aa34d7531183c9ac6f7713ba14212b02Dan Williams 0, 0)) 13538059ec2bd2ce9e4709f49f34795aa0944287908Steven Rostedt# define free_pages(x, y) munmap((void *)(x), PAGE_SIZE << (y)) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void cpu_relax(void) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Nothing */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef HZ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HZ 1000 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline uint32_t raid6_jiffies(void) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timeval tv; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gettimeofday(&tv, NULL); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return tv.tv_sec*1000 + tv.tv_usec/1000; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* ! __KERNEL__ */ 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* LINUX_RAID_RAID6_H */ 154