[Skiboot] [PATCH 13/13] add nx-842 self test

Dan Streetman ddstreet at ieee.org
Tue Mar 17 08:24:09 AEDT 2015


Add selftest module for NX-842 hardware driver.

Signed-off-by: Dan Streetman <ddstreet at ieee.org>
---
 drivers/crypto/nx/Kconfig       |  10 +-
 drivers/crypto/nx/Makefile      |   2 +
 drivers/crypto/nx/nx-842-test.c | 728 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 739 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/nx/nx-842-test.c

diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
index 894aa6c..e5b7f2d 100644
--- a/drivers/crypto/nx/Kconfig
+++ b/drivers/crypto/nx/Kconfig
@@ -1,5 +1,5 @@
 config CRYPTO_DEV_NX_ENCRYPT
-	tristate "Encryption acceleration support on pSeries platforms"
+	tristate "Encryption acceleration support on pSeries platform"
 	depends on IBMVIO && !CPU_LITTLE_ENDIAN
 	default y
 	select CRYPTO_AES
@@ -45,3 +45,11 @@ config CRYPTO_DEV_NX_POWERNV_COMPRESS
 	  module supports acceleration for compressing memory with the 842
 	  algorithm.  This supports NX hardware on the PowerNV platform.
 	  If you choose 'M' here, this module will be called nx_compress_powernv.
+
+config CRYPTO_DEV_NX_SELFTEST
+	tristate "Compression acceleration self-test"
+	depends on CRYPTO_DEV_NX_COMPRESS
+	default n
+	help
+	  Provides debugfs interface to run self-tests to verify driver and hw
+	  functionality.
diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index 82221f2..f27cf35 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -13,6 +13,8 @@ nx-crypto-objs := nx.o \
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS) += nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_PSERIES_COMPRESS) += nx-compress-pseries.o
 obj-$(CONFIG_CRYPTO_DEV_NX_POWERNV_COMPRESS) += nx-compress-powernv.o
+obj-$(CONFIG_CRYPTO_DEV_NX_SELFTEST) += nx-compress-test.o
 nx-compress-objs := nx-842.o
 nx-compress-pseries-objs := nx-842-pseries.o
 nx-compress-powernv-objs := nx-842-powernv.o
+nx-compress-test-objs := nx-842-test.o
diff --git a/drivers/crypto/nx/nx-842-test.c b/drivers/crypto/nx/nx-842-test.c
new file mode 100644
index 0000000..4775c42
--- /dev/null
+++ b/drivers/crypto/nx/nx-842-test.c
@@ -0,0 +1,728 @@
+/*
+ * Self-test for IBM 842 compression accelerator
+ *
+ * Copyright (C) 2015 Dan Streetman, IBM Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/crypto.h>
+#include <linux/nx842.h>
+#include <linux/sw842.h>
+
+#include "nx-842.h"
+
+#define MODULE_NAME "nx842-compress-test"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dan Streetman <ddstreet at ieee.org>");
+MODULE_DESCRIPTION("842 H/W Compression driver self-tests");
+
+#define TEST_BUF_ORDER		(2)
+#define TEST_BUF_SIZE		(PAGE_SIZE * (1 << TEST_BUF_ORDER))
+
+/* these combined must be < TEST_BUF_SIZE */
+#define MAX_TEST_START		(PAGE_SIZE)
+#define MAX_TEST_LEN		(PAGE_SIZE * 3)
+
+#define DBG_BUF_LINE_SIZE	(0x10)
+#define DBG_BUF_LINES_MAX	(0x40)
+#define DBG_BUF_LEN_MAX		(DBG_BUF_LINE_SIZE * DBG_BUF_LINES_MAX)
+
+struct test_arg_param {
+	struct crypto_comp *tfm;
+	void *wmem;
+};
+
+struct test_selftest_param {
+	char *name;
+	int (*constraints)(struct nx842_constraints *constraints);
+	struct semaphore lock;
+	struct task_struct *kthread;
+	unsigned char *a, *b, *c;
+	unsigned int astart, bstart, cstart;
+	unsigned int alen, blen, clen;
+	struct test_arg_param arg;
+	unsigned long comp_bps, decomp_bps, sw_bps;
+	int (*comp)(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len,
+			struct test_arg_param *p);
+	int (*decomp)(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len,
+			struct test_arg_param *p);
+	int (*sw_decomp)(const unsigned char *in, int in_len,
+			unsigned char *out, int *out_len);
+};
+
+static struct test_selftest_param test_selftest_param,
+	test_crypto842_selftest_param;
+
+static int test_crypto842_comp(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len, struct test_arg_param *p)
+{
+	return crypto_comp_compress(p->tfm, in, in_len, out, out_len);
+}
+static int test_crypto842_decomp(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len, struct test_arg_param *p)
+{
+	return crypto_comp_decompress(p->tfm, in, in_len, out, out_len);
+}
+static int test_nx842_comp(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len, struct test_arg_param *p)
+{
+	return nx842_compress(in, in_len, out, out_len, p->wmem);
+}
+static int test_nx842_decomp(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len, struct test_arg_param *p)
+{
+	return nx842_decompress(in, in_len, out, out_len, p->wmem);
+}
+
+static void debug_buffer(char *msg, unsigned char *buf, unsigned int len)
+{
+	pr_debug("%s\n", msg);
+
+	print_hex_dump_debug("",  DUMP_PREFIX_OFFSET, 16, 1, buf,
+			min_t(unsigned int, len, DBG_BUF_LEN_MAX), 0);
+}
+
+#define params_pr(t, msg, s, al, bl, cl, c)	pr_##t(			\
+	"%s  start 0x%x alen 0x%x blen 0x%x clen 0x%x "			\
+	" align 0x%x mult 0x%x min 0x%x max 0x%x\n",			\
+	(msg), (s), (al), (bl), (cl),					\
+	(c)->alignment, (c)->multiple, (c)->minimum, (c)->maximum);
+#define params_debug(msg, s, al, bl, cl, c)	params_pr(debug,	\
+	msg, s, al, bl, cl, c)
+#define params_err(msg, s, al, bl, cl, c)	params_pr(err,		\
+	msg, s, al, bl, cl, c)
+
+static unsigned long calc_bps(u64 bps, u64 bytes, u64 start)
+{
+	u64 bpus = (bps + bytes) * 1000000;
+	u64 us = 1000000 + (get_tb() - start) / tb_ticks_per_usec;
+
+	return bpus / us;
+}
+
+static int expected_fail(bool condition, char* testname, char *condname,
+			int ret, int start, unsigned int alen,
+			unsigned int blen, unsigned int clen,
+			struct nx842_constraints *constraints)
+{
+	if (condition) {
+		char *fmt = "%s self test (%s) expected to fail, but didn't.";
+		char msg[256];
+
+		if (ret)
+			return 1;
+
+		snprintf(msg, 256, fmt, testname, condname);
+
+		params_debug(msg, start, alen, blen, clen, constraints);
+	}
+
+	return 0;
+}
+
+static int test_check_expected_fail(char *testname,
+			int ret, int start, unsigned int alen,
+			unsigned int blen, unsigned int clen,
+			struct nx842_constraints *constraints)
+{
+	unsigned int lens[3] = { alen, blen, clen, };
+	char *names[3] = { "a", "b", "c", };
+	int i;
+
+	if (expected_fail(start % constraints->alignment, testname,
+			"invalid align", ret, start, alen, blen, clen, constraints))
+		return -1;
+
+	for (i = 0; i < 3; i++) {
+		unsigned int l = lens[i];
+		char *n = names[i];
+		char reason[256];
+
+		if (!l)
+			continue;
+
+		snprintf(reason, 256, "%s len invalid", n);
+		if (expected_fail(l % constraints->multiple, testname,
+				reason, ret, start, alen, blen, clen, constraints))
+			return -1;
+
+		snprintf(reason, 256, "%s len under min", n);
+		if (expected_fail(l < constraints->minimum, testname,
+				reason, ret, start, alen, blen, clen, constraints))
+			return -1;
+
+		snprintf(reason, 256, "%s len over max", n);
+		if (expected_fail(l > constraints->maximum, testname,
+				reason, ret, start, alen, blen, clen, constraints))
+			return -1;
+	}
+
+	return 0;
+}
+
+static int test_check_valid_data(char *testname,
+			unsigned char *a, int start, unsigned int alen,
+			unsigned char *b, unsigned int blen,
+			unsigned char *c, unsigned int clen,
+			struct nx842_constraints *constraints)
+{
+	if (alen != clen) {
+		char *fmt = "%s self test length mismatch.";
+		char msg[256];
+
+		snprintf(msg, 256, fmt, testname);
+		params_err(msg, start, alen, blen, clen, constraints);
+		return -1;
+	}
+
+	if (memcmp(&a[start], c, alen)) {
+		char *fmt = "%s self test data mismatch.";
+		char msg[256];
+
+		snprintf(msg, 256, fmt, testname);
+		params_err(msg, start, alen, blen, clen, constraints);
+
+		debug_buffer("original data", &a[start], alen);
+		debug_buffer("compressed data", b, blen);
+		debug_buffer("decompressed data", c, clen);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int test_sw_decomp(struct test_selftest_param *p)
+{
+	struct nx842_constraints nc = { 0, 0, 0, 0, };
+	unsigned long start;
+	int ret;
+
+	/* can't sw decomp with crypto/842.c
+	 * (it does sw decomp internally if needed)
+	 */
+	if (!p->sw_decomp)
+		return 0;
+
+	p->clen = TEST_BUF_SIZE;
+
+	memset(p->c, 0, p->clen);
+
+	start = get_tb();
+
+	ret = p->sw_decomp(p->b, p->blen, p->c, &p->clen);
+
+	if (ret) {
+		params_err("sw decompress self test failed.",
+				p->astart, p->alen, p->blen, p->clen, &nc);
+		debug_buffer("compressed data", p->b, p->blen);
+		return -1;
+	}
+
+	if (test_check_valid_data("sw decompress",
+			p->a, p->astart, p->alen,
+			p->b, p->blen, p->c, p->clen, &nc))
+		return -1;
+
+	p->sw_bps = calc_bps(p->sw_bps, p->clen, start);
+
+	return 0;
+}
+
+static int test_decomp(struct test_selftest_param *p)
+{
+	struct nx842_constraints constraints;
+	unsigned long start;
+	int ret;
+
+	if ((ret = p->constraints(&constraints))) {
+		pr_err("error getting nx842 constraints : %d\n", ret);
+		return ret;
+	}
+
+	p->clen = min_t(int, constraints.maximum, TEST_BUF_SIZE);
+	p->clen = round_down(p->clen, constraints.multiple);
+
+	memset(p->c, 0, p->clen);
+
+	start = get_tb();
+
+	ret = p->decomp(p->b, p->blen, p->c, &p->clen, &p->arg);
+
+	// TODO - add decomp tests with invalid align and len
+	if (test_check_expected_fail("decompression", ret,
+			p->astart, p->alen, p->blen, p->clen, &constraints))
+		return 0;
+
+	if (ret) {
+		params_err("decompression self test failed.",
+				p->astart, p->alen, p->blen, p->clen, &constraints);
+		debug_buffer("compressed data", p->b, p->blen);
+		return -1;
+	}
+
+	if (test_check_valid_data("decompress",
+			p->a, p->astart, p->alen,
+			p->b, p->blen, p->c, p->clen, &constraints))
+		return -1;
+
+	p->decomp_bps = calc_bps(p->decomp_bps, p->clen, start);
+
+	return test_sw_decomp(p);
+}
+
+static int test_comp(struct test_selftest_param *p)
+{
+	struct nx842_constraints constraints;
+	unsigned long start;
+	int ret;
+
+	if ((ret = p->constraints(&constraints))) {
+		pr_err("error getting nx842 constraints : %d\n", ret);
+		return ret;
+	}
+
+	p->blen = min_t(int, constraints.maximum, TEST_BUF_SIZE);
+	p->blen = round_down(p->blen, constraints.multiple);
+
+	memset(p->b, 0, p->blen);
+
+	start = get_tb();
+
+	ret = p->comp(&p->a[p->astart], p->alen, p->b, &p->blen, &p->arg);
+
+	if (test_check_expected_fail("compression", ret,
+			p->astart, p->alen, p->blen, 0, &constraints))
+		return 0;
+
+	if (ret) {
+		params_err("compression self test failed.",
+				p->astart, p->alen, p->blen, 0, &constraints);
+		debug_buffer("original data", p->a, p->alen);
+		return -1;
+	}
+
+	p->comp_bps = calc_bps(p->comp_bps, p->alen, start);
+
+	return test_decomp(p);
+}
+
+static int test_crypto842_constraints(struct nx842_constraints *constraints)
+{
+	constraints->alignment = 1;
+	constraints->multiple = 1;
+	constraints->minimum = 1;
+	constraints->maximum = PAGE_SIZE * 4; /* arbitrary */
+
+	return 0;
+}
+
+static int test_run(void *data)
+{
+	struct test_selftest_param *p = data;
+	int i, ret = 0, pct = 0, test_n = 0, test_total;
+
+	for (i = 0; i*16+15 < TEST_BUF_SIZE; i++)
+		memset(&p->a[i*16], i%0xff, 16);
+
+	pr_info("%s starting.\n", p->name);
+
+	BUILD_BUG_ON(MAX_TEST_START + MAX_TEST_LEN > TEST_BUF_SIZE);
+
+	/* p->alen should have been set to > 0 by file write arg */
+	test_total = MAX_TEST_LEN - p->alen;
+	for (; p->alen <= MAX_TEST_LEN; p->alen++) {
+		for (p->astart = 0; p->astart < MAX_TEST_START; p->astart++) {
+			if ((ret = test_comp(p)) || kthread_should_stop())
+				goto end;
+			if (!(p->astart % 0x1000))
+				schedule(); /* don't lock up the cpu */
+		}
+		if (((test_n++)*100)/test_total >= pct) {
+			pr_info("self test %d%% complete.\n", pct);
+			pct += 1;
+		}
+	}
+
+end:
+	if (kthread_should_stop())
+		pr_info("self test interrupted\n");
+
+	pr_info("self test completed.\n");
+
+	p->kthread = NULL;
+	module_put(THIS_MODULE);
+
+	return ret;
+}
+
+/* Self-test */
+
+static ssize_t __test_selftest_read(struct file *file,
+			char __user *buf, size_t len, loff_t *off,
+			struct test_selftest_param *p)
+{
+	int ret = 0;
+	char tmp[128];
+
+	if (*off > 0)
+		return 0;
+
+	if (down_interruptible(&p->lock))
+		return -EBUSY;
+
+	if (p->kthread) {
+		schedule_timeout_interruptible(10); /* slow down the updates */
+		snprintf(tmp, 128, "astart %x/%lx alen %x/%lx "
+			 "MBps: %ld comp %ld decomp %ld sw decomp"
+			 "      \r",
+			 p->astart, MAX_TEST_START, p->alen, MAX_TEST_LEN,
+			 p->comp_bps / 1000000,
+			 p->decomp_bps / 1000000,
+			 p->sw_bps / 1000000);
+	} else {
+		snprintf(tmp, 128,
+			 "\nself test not running\n");
+		*off = strlen(tmp);
+	}
+
+	len = min(len, strlen(tmp));
+
+	if (copy_to_user(buf, tmp, len))
+		ret = -EFAULT;
+
+	up(&p->lock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t __test_selftest_write(struct file *file,
+			const char __user *buf, size_t len, loff_t *off,
+			struct test_selftest_param *p)
+{
+	int ret = 0, arg;
+
+	if (*off > 0 || len < 1)
+		return -EINVAL;
+
+	if ((ret = kstrtoint_from_user(buf, len, 0, &arg)))
+		return ret;
+
+	if (down_interruptible(&p->lock))
+		return -EBUSY;
+
+	if (arg > 0) {
+		if (!p->kthread) {
+			__module_get(THIS_MODULE);
+			p->alen = arg;
+			p->kthread = kthread_run(test_run, p, p->name);
+			if (IS_ERR(p->kthread)) {
+				ret = PTR_ERR(p->kthread);
+				p->kthread = NULL;
+				module_put(THIS_MODULE);
+			}
+		}
+	} else if (!arg) {
+		if (p->kthread)
+			ret = kthread_stop(p->kthread);
+	} else {
+		ret = -EINVAL;
+	}
+
+	if (!ret)
+		*off = 1;
+
+	up(&p->lock);
+
+	return ret ? ret : len;
+}
+
+#define TEST_FUNC(name)							\
+static ssize_t test_##name##_read(struct file *file,			\
+		char __user *buf, size_t len, loff_t *off)		\
+{									\
+	return __test_selftest_read(file, buf, len, off,		\
+			&test_##name##_param);				\
+}									\
+static ssize_t test_##name##_write(struct file *file,			\
+		const char __user *buf, size_t len, loff_t *off)	\
+{									\
+	return __test_selftest_write(file, buf, len, off,		\
+			&test_##name##_param);				\
+}
+
+TEST_FUNC(selftest);
+TEST_FUNC(crypto842_selftest);
+
+/************************************/
+/* Provided buffer comp/decomp test */
+
+struct test_buffer_param {
+	struct semaphore lock;
+	unsigned char *buffer;
+	unsigned int len;
+	struct test_arg_param arg;
+	int (*op)(const unsigned char *in, unsigned int in_len,
+			unsigned char *out, unsigned int *out_len,
+			struct test_arg_param *p);
+};
+
+static struct test_buffer_param test_comp_param, test_decomp_param,
+	test_crypto842_comp_param, test_crypto842_decomp_param;
+
+static ssize_t test_buffer_read(struct file *file, char __user *buf, size_t len,
+			loff_t *off, struct test_buffer_param *p)
+{
+	ssize_t ret;
+
+	pr_debug("buffer read f_pos %d off %d len %d\n",
+			(int)file->f_pos, (int)*off, (int)len);
+
+	if (file->f_pos > 0 || *off > 0)
+		return 0;
+
+	if (down_interruptible(&p->lock))
+		return -EBUSY;
+
+	pr_debug("buffer read p->len %d\n", p->len);
+
+	if (!p->len) {
+		ret = 0;
+	} else if (len < p->len) {
+		ret = -ENOSPC;
+	} else if (copy_to_user(buf, p->buffer, p->len)) {
+		ret = -EFAULT;
+	} else {
+		*off = ret = p->len;
+		p->len = 0;
+	}
+
+	up(&p->lock);
+
+	return ret;
+}
+
+static ssize_t test_buffer_write(struct file *file, const char __user *buf,
+			size_t len, loff_t *off, struct test_buffer_param *p)
+{
+	int ret;
+	unsigned char *in;
+
+	pr_debug("buffer write f_pos %d off %d len %d\n",
+			(int)file->f_pos, (int)*off, (int)len);
+
+	if (file->f_pos > 0 || *off > 0 || len < 1)
+		return -EINVAL;
+	else if (len > (PAGE_SIZE * 4))
+		return -ENOSPC;
+
+	if (down_interruptible(&p->lock))
+		return -EBUSY;
+
+	pr_debug("buffer write was p->len %d\n", p->len);
+
+	p->len = TEST_BUF_SIZE;
+
+	if (!(in = (unsigned char*)__get_free_page(GFP_KERNEL)))
+		ret = -ENOMEM;
+	else if (copy_from_user(in, buf, len))
+		ret = -EFAULT;
+	else if (!(ret = p->op(in, len,
+			p->buffer, &p->len, &p->arg)))
+		*off = ret = len;
+
+	free_page((unsigned long)in);
+
+	up(&p->lock);
+
+	return ret;
+}
+
+#define TEST_BUFFER_FUNC(name)							\
+static ssize_t test_##name##_read(struct file *file,			\
+		char __user *buf, size_t len, loff_t *off)		\
+{									\
+	return test_buffer_read(file, buf, len, off,			\
+			&test_##name##_param);				\
+}									\
+static ssize_t test_##name##_write(struct file *file,			\
+		const char __user *buf, size_t len, loff_t *off)	\
+{									\
+	return test_buffer_write(file, buf, len, off,			\
+			&test_##name##_param);				\
+}
+
+TEST_BUFFER_FUNC(comp);
+TEST_BUFFER_FUNC(decomp);
+TEST_BUFFER_FUNC(crypto842_comp);
+TEST_BUFFER_FUNC(crypto842_decomp);
+
+#define TEST_FOPS(name)						\
+	static struct file_operations test_##name##_ops = {	\
+		.owner =	THIS_MODULE,			\
+		.read =		test_##name##_read,		\
+		.write =	test_##name##_write,		\
+	};
+
+TEST_FOPS(selftest);
+TEST_FOPS(comp);
+TEST_FOPS(decomp);
+TEST_FOPS(crypto842_selftest);
+TEST_FOPS(crypto842_comp);
+TEST_FOPS(crypto842_decomp);
+
+static struct dentry *test_root = NULL;
+
+static void test_exit(void)
+{
+	struct test_selftest_param *selftest_params[] = {
+		&test_selftest_param, &test_crypto842_selftest_param, };
+	struct test_buffer_param *buffer_params[] = {
+		&test_comp_param, &test_decomp_param,
+		&test_crypto842_comp_param, &test_crypto842_decomp_param, };
+	int i;
+
+	debugfs_remove_recursive(test_root);
+
+	for (i = 0; i < ARRAY_SIZE(selftest_params); i++) {
+		struct test_selftest_param *p = selftest_params[i];
+
+		if (p->arg.tfm)
+			crypto_free_comp(p->arg.tfm);
+		kfree(p->arg.wmem);
+		free_pages((unsigned long)p->a, TEST_BUF_ORDER);
+		free_pages((unsigned long)p->b, TEST_BUF_ORDER);
+		free_pages((unsigned long)p->c, TEST_BUF_ORDER);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(buffer_params); i++) {
+		struct test_buffer_param *p = buffer_params[i];
+
+		if (p->arg.tfm)
+			crypto_free_comp(p->arg.tfm);
+		kfree(p->arg.wmem);
+		free_pages((unsigned long)p->buffer, TEST_BUF_ORDER);
+	}
+}
+module_exit(test_exit);
+
+static int __init test_init(void)
+{
+	struct dentry *crypto_842_root;
+	struct test_selftest_param *selftest_params[] = {
+		&test_selftest_param, &test_crypto842_selftest_param, };
+	struct test_buffer_param *buffer_params[] = {
+		&test_comp_param, &test_decomp_param,
+		&test_crypto842_comp_param, &test_crypto842_decomp_param, };
+	int i, ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(selftest_params); i++) {
+		struct test_selftest_param *p = selftest_params[i];
+
+		sema_init(&p->lock, 1);
+
+		p->arg.tfm = crypto_alloc_comp("842", 0, 0);
+		p->arg.wmem = kmalloc(NX842_MEM_COMPRESS, GFP_KERNEL);
+		p->a = (unsigned char*)__get_free_pages(GFP_KERNEL,
+				TEST_BUF_ORDER);
+		p->b = (unsigned char*)__get_free_pages(GFP_KERNEL,
+				TEST_BUF_ORDER);
+		p->c = (unsigned char*)__get_free_pages(GFP_KERNEL,
+				TEST_BUF_ORDER);
+		if (IS_ERR(p->arg.tfm)) {
+			p->arg.tfm = NULL;
+			ret = -EINVAL;
+			goto fail;
+		}
+		if (!p->arg.wmem || !p->a || !p->b || !p->c) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(buffer_params); i++) {
+		struct test_buffer_param *p = buffer_params[i];
+
+		sema_init(&p->lock, 1);
+		p->len = 0;
+
+		p->arg.tfm = crypto_alloc_comp("842", 0, 0);
+		p->arg.wmem = kmalloc(NX842_MEM_COMPRESS, GFP_KERNEL);
+		p->buffer = (unsigned char *)__get_free_pages(GFP_KERNEL,
+				TEST_BUF_ORDER);
+		if (IS_ERR(p->arg.tfm)) {
+			p->arg.tfm = NULL;
+			ret = -EINVAL;
+			goto fail;
+		}
+		if (!p->buffer || !p->arg.wmem) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+	}
+
+	test_comp_param.op = test_nx842_comp;
+	test_decomp_param.op = test_nx842_decomp;
+	test_crypto842_comp_param.op = test_crypto842_comp;
+	test_crypto842_decomp_param.op = test_crypto842_decomp;
+
+	test_selftest_param.name = "nx842 selftest";
+	test_selftest_param.constraints = nx842_constraints;
+	test_selftest_param.comp = test_nx842_comp;
+	test_selftest_param.decomp = test_nx842_decomp;
+	test_selftest_param.sw_decomp = sw842_decompress;
+	test_crypto842_selftest_param.name = "crypto 842 selftest";
+	test_crypto842_selftest_param.constraints =
+		test_crypto842_constraints;
+	test_crypto842_selftest_param.comp = test_crypto842_comp;
+	test_crypto842_selftest_param.decomp = test_crypto842_decomp;
+	test_crypto842_selftest_param.sw_decomp = NULL;
+
+	if (!debugfs_initialized()) {
+		ret = -ENODEV;
+	} else if (!(test_root =
+			debugfs_create_dir("nx_compress_test", NULL))) {
+		ret = -ENOMEM;
+	} else if (!(crypto_842_root =
+			debugfs_create_dir("crypto_842", test_root))) {
+		ret = -ENOMEM;
+	} else {
+		debugfs_create_file("selftest", S_IRUGO | S_IWUSR,
+				test_root, NULL, &test_selftest_ops);
+		debugfs_create_file("compress", S_IRUGO | S_IWUSR,
+				test_root, NULL, &test_comp_ops);
+		debugfs_create_file("decompress", S_IRUGO | S_IWUSR,
+				test_root, NULL, &test_decomp_ops);
+
+		debugfs_create_file("selftest", S_IRUGO | S_IWUSR,
+				crypto_842_root, NULL, &test_crypto842_selftest_ops);
+		debugfs_create_file("compress", S_IRUGO | S_IWUSR,
+				crypto_842_root, NULL, &test_crypto842_comp_ops);
+		debugfs_create_file("decompress", S_IRUGO | S_IWUSR,
+				crypto_842_root, NULL, &test_crypto842_decomp_ops);
+	}
+
+fail:
+	if (ret)
+		test_exit();
+
+	return ret;
+}
+module_init(test_init);
-- 
2.1.0



More information about the Skiboot mailing list