This allows to test & run multiple parallel crypto ahash contexts. Each of the test vector under the ahash speed test template is started under a separate kthread. Signed-off-by: Vakul Garg <vakul@xxxxxxxxxxxxx> --- crypto/tcrypt.c | 164 +++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 129 insertions(+), 35 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 7ae2130..e879de9 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -33,6 +33,7 @@ #include <linux/jiffies.h> #include <linux/timex.h> #include <linux/interrupt.h> +#include <linux/kthread.h> #include "tcrypt.h" #include "internal.h" @@ -497,9 +498,9 @@ static inline int do_one_ahash_op(struct ahash_request *req, int ret) } return ret; } - static int test_ahash_jiffies_digest(struct ahash_request *req, int blen, - char *out, int sec) + char *out, int sec, + struct completion *comp) { unsigned long start, end; int bcount; @@ -512,6 +513,11 @@ static int test_ahash_jiffies_digest(struct ahash_request *req, int blen, return ret; } + wait_for_completion_interruptible(comp); + + pr_info("test (%5u byte blocks,%5u bytes per update,%4u updates): ", + blen, blen, blen/blen); + printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); @@ -519,14 +525,15 @@ static int test_ahash_jiffies_digest(struct ahash_request *req, int blen, } static int test_ahash_jiffies(struct ahash_request *req, int blen, - int plen, char *out, int sec) + int plen, char *out, int sec, + struct completion *comp) { unsigned long start, end; int bcount, pcount; int ret; if (plen == blen) - return test_ahash_jiffies_digest(req, blen, out, sec); + return test_ahash_jiffies_digest(req, blen, out, sec, comp); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { @@ -544,6 +551,11 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen, return ret; } + wait_for_completion_interruptible(comp); + + pr_info("test (%5u byte blocks,%5u bytes per update,%4u updates): ", + blen, plen, blen/plen); + pr_cont("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); @@ -551,7 +563,7 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen, } static int test_ahash_cycles_digest(struct ahash_request *req, int blen, - char *out) + char *out, struct completion *comp) { unsigned long cycles = 0; int ret, i; @@ -582,6 +594,11 @@ out: if (ret) return ret; + wait_for_completion_interruptible(comp); + + pr_info("test (%5u byte blocks,%5u bytes per update,%4u updates): ", + blen, blen, blen/blen); + pr_cont("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); @@ -589,13 +606,13 @@ out: } static int test_ahash_cycles(struct ahash_request *req, int blen, - int plen, char *out) + int plen, char *out, struct completion *comp) { unsigned long cycles = 0; int i, pcount, ret; if (plen == blen) - return test_ahash_cycles_digest(req, blen, out); + return test_ahash_cycles_digest(req, blen, out, comp); /* Warm-up run. */ for (i = 0; i < 4; i++) { @@ -636,51 +653,119 @@ static int test_ahash_cycles(struct ahash_request *req, int blen, } out: + if (ret) return ret; + wait_for_completion_interruptible(comp); + + pr_info("test (%5u byte blocks,%5u bytes per update,%4u updates): ", + blen, plen, blen/plen); + pr_cont("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); return 0; } -static void test_ahash_speed(const char *algo, unsigned int sec, - struct hash_speed *speed) +struct hash_test { + const char *algo; + unsigned int blen; + unsigned int plen; + unsigned int klen; + unsigned int sec; + struct completion print; + struct completion finish; +}; + +static int test_ahash_speed_thread(void *data) { struct scatterlist sg[TVMEMSIZE]; struct tcrypt_result tresult; struct ahash_request *req; struct crypto_ahash *tfm; static char output[1024]; - int i, ret; - - printk(KERN_INFO "\ntesting speed of async %s\n", algo); + int ret; + struct hash_test *test = data; - tfm = crypto_alloc_ahash(algo, 0, 0); + tfm = crypto_alloc_ahash(test->algo, 0, 0); if (IS_ERR(tfm)) { pr_err("failed to load transform for %s: %ld\n", - algo, PTR_ERR(tfm)); - return; + test->algo, PTR_ERR(tfm)); + ret = PTR_ERR(tfm); + goto stop; } if (crypto_ahash_digestsize(tfm) > sizeof(output)) { pr_err("digestsize(%u) > outputbuffer(%zu)\n", crypto_ahash_digestsize(tfm), sizeof(output)); - goto out; + ret = -EINVAL; + goto err; } test_hash_sg_init(sg); req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { pr_err("ahash request allocation failure\n"); - goto out; + ret = PTR_ERR(req); + goto err; } init_completion(&tresult.completion); ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, &tresult); + + ahash_request_set_crypt(req, sg, output, test->plen); + + if (sec) + ret = test_ahash_jiffies(req, test->blen, + test->plen, output, sec, + &test->print); + else + ret = test_ahash_cycles(req, test->blen, + test->plen, output, &test->print); + + if (ret) + pr_err("hashing failed ret=%d\n", ret); + + ahash_request_free(req); + +err: + crypto_free_ahash(tfm); + +stop: + complete(&test->finish); + + return ret; +} + + +static void test_ahash_speed(const char *algo, unsigned int sec, + struct hash_speed *speed) +{ + int i, num_tests; + struct hash_test *tests; + struct task_struct **threads; + + pr_info("\ntesting speed of async %s\n", algo); + + /* Count the number of tests to be done */ + for (i = 0; speed[i].blen != 0; i++) + ; + + threads = kzalloc(i * sizeof(struct task_struct *), GFP_KERNEL); + if (!threads) { + pr_err("Memory alloc for threads failed\n"); + return; + } + + tests = kzalloc(i * sizeof(struct hash_test), GFP_KERNEL); + if (!threads) { + pr_err("Memory alloc for hash tests failed\n"); + goto err; + } + for (i = 0; speed[i].blen != 0; i++) { if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { pr_err("template (%u) too big for tvmem (%lu)\n", @@ -688,29 +773,38 @@ static void test_ahash_speed(const char *algo, unsigned int sec, break; } - pr_info("test%3u " - "(%5u byte blocks,%5u bytes per update,%4u updates): ", - i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); - - ahash_request_set_crypt(req, sg, output, speed[i].plen); - - if (sec) - ret = test_ahash_jiffies(req, speed[i].blen, - speed[i].plen, output, sec); - else - ret = test_ahash_cycles(req, speed[i].blen, - speed[i].plen, output); - - if (ret) { - pr_err("hashing failed ret=%d\n", ret); + tests[i].algo = algo; + tests[i].blen = speed[i].blen; + tests[i].plen = speed[i].plen; + tests[i].klen = speed[i].klen; + init_completion(&tests[i].print); + init_completion(&tests[i].finish); + + /* Create a kthread for the test vector in template */ + threads[i] = kthread_run(test_ahash_speed_thread, &tests[i], + "tcrypt_ahash_%d", i); + if (IS_ERR(threads[i])) { + pr_err("tcrypt_ahash_%d creation failed\n", i); break; } } - ahash_request_free(req); + num_tests = i; -out: - crypto_free_ahash(tfm); + /* TODO: Let all threads pass a barrier so that they start + * crypto tests together. + */ + + /* Signal threads one by one for printing results and stop them*/ + for (i = 0; i < num_tests; i++) { + complete(&tests[i].print); + /*kthread_stop(threads[i]);*/ + wait_for_completion_interruptible(&tests[i].finish); + } + +err: + kfree(threads); + kfree(tests); } static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret) -- 1.7.7.6 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html