/*
 * asynchronous raid6 recovery self test
 * Copyright (c) 2009, Intel Corporation.
 *
 * based on drivers/md/raid6test/test.c:
 * 	Copyright 2002-2007 H. Peter Anvin
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#include <linux/async_tx.h>
#include <linux/gfp.h>
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/module.h>

#undef pr
#define pr(fmt, args...) pr_info("raid6test: " fmt, ##args)

#define NDISKS 64 /* Including P and Q */

static struct page *dataptrs[NDISKS];
static addr_conv_t addr_conv[NDISKS];
static struct page *data[NDISKS+3];
static struct page *spare;
static struct page *recovi;
static struct page *recovj;

static void callback(void *param)
{
	struct completion *cmp = param;

	complete(cmp);
}

static void makedata(int disks)
{
	int i;

	for (i = 0; i < disks; i++) {
		prandom_bytes(page_address(data[i]), PAGE_SIZE);
		dataptrs[i] = data[i];
	}
}

static char disk_type(int d, int disks)
{
	if (d == disks - 2)
		return 'P';
	else if (d == disks - 1)
		return 'Q';
	else
		return 'D';
}

/* Recover two failed blocks. */
static void raid6_dual_recov(int disks, size_t bytes, int faila, int failb, struct page **ptrs)
{
	struct async_submit_ctl submit;
	struct completion cmp;
	struct dma_async_tx_descriptor *tx = NULL;
	enum sum_check_flags result = ~0;

	if (faila > failb)
		swap(faila, failb);

	if (failb == disks-1) {
		if (faila == disks-2) {
			/* P+Q failure.  Just rebuild the syndrome. */
			init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);
			tx = async_gen_syndrome(ptrs, 0, disks, bytes, &submit);
		} else {
			struct page *blocks[disks];
			struct page *dest;
			int count = 0;
			int i;

			/* data+Q failure.  Reconstruct data from P,
			 * then rebuild syndrome
			 */
			for (i = disks; i-- ; ) {
				if (i == faila || i == failb)
					continue;
				blocks[count++] = ptrs[i];
			}
			dest = ptrs[faila];
			init_async_submit(&submit, ASYNC_TX_XOR_ZERO_DST, NULL,
					  NULL, NULL, addr_conv);
			tx = async_xor(dest, blocks, 0, count, bytes, &submit);

			init_async_submit(&submit, 0, tx, NULL, NULL, addr_conv);
			tx = async_gen_syndrome(ptrs, 0, disks, bytes, &submit);
		}
	} else {
		if (failb == disks-2) {
			/* data+P failure. */
			init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);
			tx = async_raid6_datap_recov(disks, bytes, faila, ptrs, &submit);
		} else {
			/* data+data failure. */
			init_async_submit(&submit, 0, NULL, NULL, NULL, addr_conv);
			tx = async_raid6_2data_recov(disks, bytes, faila, failb, ptrs, &submit);
		}
	}
	init_completion(&cmp);
	init_async_submit(&submit, ASYNC_TX_ACK, tx, callback, &cmp, addr_conv);
	tx = async_syndrome_val(ptrs, 0, disks, bytes, &result, spare, &submit);
	async_tx_issue_pending(tx);

	if (wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)) == 0)
		pr("%s: timeout! (faila: %d failb: %d disks: %d)\n",
		   __func__, faila, failb, disks);

	if (result != 0)
		pr("%s: validation failure! faila: %d failb: %d sum_check_flags: %x\n",
		   __func__, faila, failb, result);
}

static int test_disks(int i, int j, int disks)
{
	int erra, errb;

	memset(page_address(recovi), 0xf0, PAGE_SIZE);
	memset(page_address(recovj), 0xba, PAGE_SIZE);

	dataptrs[i] = recovi;
	dataptrs[j] = recovj;

	raid6_dual_recov(disks, PAGE_SIZE, i, j, dataptrs);

	erra = memcmp(page_address(data[i]), page_address(recovi), PAGE_SIZE);
	errb = memcmp(page_address(data[j]), page_address(recovj), PAGE_SIZE);

	pr("%s(%d, %d): faila=%3d(%c)  failb=%3d(%c)  %s\n",
	   __func__, i, j, i, disk_type(i, disks), j, disk_type(j, disks),
	   (!erra && !errb) ? "OK" : !erra ? "ERRB" : !errb ? "ERRA" : "ERRAB");

	dataptrs[i] = data[i];
	dataptrs[j] = data[j];

	return erra || errb;
}

static int test(int disks, int *tests)
{
	struct dma_async_tx_descriptor *tx;
	struct async_submit_ctl submit;
	struct completion cmp;
	int err = 0;
	int i, j;

	recovi = data[disks];
	recovj = data[disks+1];
	spare  = data[disks+2];

	makedata(disks);

	/* Nuke syndromes */
	memset(page_address(data[disks-2]), 0xee, PAGE_SIZE);
	memset(page_address(data[disks-1]), 0xee, PAGE_SIZE);

	/* Generate assumed good syndrome */
	init_completion(&cmp);
	init_async_submit(&submit, ASYNC_TX_ACK, NULL, callback, &cmp, addr_conv);
	tx = async_gen_syndrome(dataptrs, 0, disks, PAGE_SIZE, &submit);
	async_tx_issue_pending(tx);

	if (wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)) == 0) {
		pr("error: initial gen_syndrome(%d) timed out\n", disks);
		return 1;
	}

	pr("testing the %d-disk case...\n", disks);
	for (i = 0; i < disks-1; i++)
		for (j = i+1; j < disks; j++) {
			(*tests)++;
			err += test_disks(i, j, disks);
		}

	return err;
}


static int raid6_test(void)
{
	int err = 0;
	int tests = 0;
	int i;

	for (i = 0; i < NDISKS+3; i++) {
		data[i] = alloc_page(GFP_KERNEL);
		if (!data[i]) {
			while (i--)
				put_page(data[i]);
			return -ENOMEM;
		}
	}

	/* the 4-disk and 5-disk cases are special for the recovery code */
	if (NDISKS > 4)
		err += test(4, &tests);
	if (NDISKS > 5)
		err += test(5, &tests);
	/* the 11 and 12 disk cases are special for ioatdma (p-disabled
	 * q-continuation without extended descriptor)
	 */
	if (NDISKS > 12) {
		err += test(11, &tests);
		err += test(12, &tests);
	}

	/* the 24 disk case is special for ioatdma as it is the boudary point
	 * at which it needs to switch from 8-source ops to 16-source
	 * ops for continuation (assumes DMA_HAS_PQ_CONTINUE is not set)
	 */
	if (NDISKS > 24)
		err += test(24, &tests);

	err += test(NDISKS, &tests);

	pr("\n");
	pr("complete (%d tests, %d failure%s)\n",
	   tests, err, err == 1 ? "" : "s");

	for (i = 0; i < NDISKS+3; i++)
		put_page(data[i]);

	return 0;
}

static void raid6_test_exit(void)
{
}

/* when compiled-in wait for drivers to load first (assumes dma drivers
 * are also compliled-in)
 */
late_initcall(raid6_test);
module_exit(raid6_test_exit);
MODULE_AUTHOR("Dan Williams <dan.j.williams@intel.com>");
MODULE_DESCRIPTION("asynchronous RAID-6 recovery self tests");
MODULE_LICENSE("GPL");
