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