Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 048a8b8c authored by Jim Kukunas's avatar Jim Kukunas Committed by NeilBrown
Browse files

lib/raid6: Add SSSE3 optimized recovery functions



Add SSSE3 optimized recovery functions, as well as a system
for selecting the most appropriate recovery functions to use.

Originally-by: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarJim Kukunas <james.t.kukunas@linux.intel.com>
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent f674ef7b
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -99,8 +99,20 @@ extern const struct raid6_calls raid6_altivec2;
extern const struct raid6_calls raid6_altivec4;
extern const struct raid6_calls raid6_altivec8;

struct raid6_recov_calls {
	void (*data2)(int, size_t, int, int, void **);
	void (*datap)(int, size_t, int, void **);
	int  (*valid)(void);
	const char *name;
	int priority;
};

extern const struct raid6_recov_calls raid6_recov_intx1;
extern const struct raid6_recov_calls raid6_recov_ssse3;

/* Algorithm list */
extern const struct raid6_calls * const raid6_algos[];
extern const struct raid6_recov_calls *const raid6_recov_algos[];
int raid6_select_algo(void);

/* Return values from chk_syndrome */
@@ -111,14 +123,16 @@ int raid6_select_algo(void);

/* Galois field tables */
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256]      __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256]      __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256]      __attribute__((aligned(256)));

/* Recovery routines */
void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
extern void (*raid6_2data_recov)(int disks, size_t bytes, int faila, int failb,
		       void **ptrs);
extern void (*raid6_datap_recov)(int disks, size_t bytes, int faila,
			void **ptrs);
void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs);
void raid6_dual_recov(int disks, size_t bytes, int faila, int failb,
		      void **ptrs);

+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_RAID6_PQ)	+= raid6_pq.o

raid6_pq-y	+= algos.o recov.o tables.o int1.o int2.o int4.o \
raid6_pq-y	+= algos.o recov.o recov_ssse3.o tables.o int1.o int2.o int4.o \
		   int8.o int16.o int32.o altivec1.o altivec2.o altivec4.o \
		   altivec8.o mmx.o sse1.o sse2.o
hostprogs-y	+= mktables
+37 −0
Original line number Diff line number Diff line
@@ -64,6 +64,20 @@ const struct raid6_calls * const raid6_algos[] = {
	NULL
};

void (*raid6_2data_recov)(int, size_t, int, int, void **);
EXPORT_SYMBOL_GPL(raid6_2data_recov);

void (*raid6_datap_recov)(int, size_t, int, void **);
EXPORT_SYMBOL_GPL(raid6_datap_recov);

const struct raid6_recov_calls *const raid6_recov_algos[] = {
#if (defined(__i386__) || defined(__x86_64__)) && !defined(__arch_um__)
	&raid6_recov_ssse3,
#endif
	&raid6_recov_intx1,
	NULL
};

#ifdef __KERNEL__
#define RAID6_TIME_JIFFIES_LG2	4
#else
@@ -72,6 +86,26 @@ const struct raid6_calls * const raid6_algos[] = {
#define time_before(x, y) ((x) < (y))
#endif

static inline void raid6_choose_recov(void)
{
	const struct raid6_recov_calls *const *algo;
	const struct raid6_recov_calls *best;

	for (best = NULL, algo = raid6_recov_algos; *algo; algo++)
		if (!best || (*algo)->priority > best->priority)
			if (!(*algo)->valid || (*algo)->valid())
				best = *algo;

	if (best) {
		raid6_2data_recov = best->data2;
		raid6_datap_recov = best->datap;

		printk("raid6: using %s recovery algorithm\n", best->name);
	} else
		printk("raid6: Yikes! No recovery algorithm found!\n");
}


/* Try to pick the best algorithm */
/* This code uses the gfmul table as convenient data set to abuse */

@@ -141,6 +175,9 @@ int __init raid6_select_algo(void)

	free_pages((unsigned long)syndromes, 1);

	/* select raid recover functions */
	raid6_choose_recov();

	return best ? 0 : -EINVAL;
}

+25 −0
Original line number Diff line number Diff line
@@ -81,6 +81,31 @@ int main(int argc, char *argv[])
	printf("EXPORT_SYMBOL(raid6_gfmul);\n");
	printf("#endif\n");

	/* Compute vector multiplication table */
	printf("\nconst u8  __attribute__((aligned(256)))\n"
		"raid6_vgfmul[256][32] =\n"
		"{\n");
	for (i = 0; i < 256; i++) {
		printf("\t{\n");
		for (j = 0; j < 16; j += 8) {
			printf("\t\t");
			for (k = 0; k < 8; k++)
				printf("0x%02x,%c", gfmul(i, j + k),
				       (k == 7) ? '\n' : ' ');
		}
		for (j = 0; j < 16; j += 8) {
			printf("\t\t");
			for (k = 0; k < 8; k++)
				printf("0x%02x,%c", gfmul(i, (j + k) << 4),
				       (k == 7) ? '\n' : ' ');
		}
		printf("\t},\n");
	}
	printf("};\n");
	printf("#ifdef __KERNEL__\n");
	printf("EXPORT_SYMBOL(raid6_vgfmul);\n");
	printf("#endif\n");

	/* Compute power-of-2 table (exponent) */
	v = 1;
	printf("\nconst u8 __attribute__((aligned(256)))\n"
+11 −4
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@
#include <linux/raid/pq.h>

/* Recover two failed data blocks. */
void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, int failb,
		       void **ptrs)
{
	u8 *p, *q, *dp, *dq;
@@ -64,10 +64,9 @@ void raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
		p++; q++;
	}
}
EXPORT_SYMBOL_GPL(raid6_2data_recov);

/* Recover failure of one data block plus the P block */
void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
void raid6_datap_recov_intx1(int disks, size_t bytes, int faila, void **ptrs)
{
	u8 *p, *q, *dq;
	const u8 *qmul;		/* Q multiplier table */
@@ -96,7 +95,15 @@ void raid6_datap_recov(int disks, size_t bytes, int faila, void **ptrs)
		q++; dq++;
	}
}
EXPORT_SYMBOL_GPL(raid6_datap_recov);


const struct raid6_recov_calls raid6_recov_intx1 = {
	.data2 = raid6_2data_recov_intx1,
	.datap = raid6_datap_recov_intx1,
	.valid = NULL,
	.name = "intx1",
	.priority = 0,
};

#ifndef __KERNEL__
/* Testing only */
Loading