Module Name:    src
Committed By:   snj
Date:           Sat Aug  5 03:59:21 UTC 2017

Modified Files:
        src/sys/opencrypto [netbsd-8]: crypto.c cryptodev.h ocryptodev.c
            xform.c xform.h

Log Message:
Pull up following revision(s) (requested by knakahara in ticket #178):
        sys/opencrypto/crypto.c: 1.92-1.100
        sys/opencrypto/cryptodev.h: 1.38-1.39
        sys/opencrypto/ocryptodev.c: 1.9-1.11
        sys/opencrypto/xform.c: revision 1.29
        sys/opencrypto/xform.h: revision 1.20
KNF
--
Apply C99-style struct initialization to enc_xform, auth_hash and comp_algo
--
make cryptoret() context softint to balance dequeuing crypto_ret_q with 
enqueuing it.
--
fix panic when using ecryption devices attached earlier than ipi_sysinit().
pointed out and tested by [email protected], thanks.
--
fix typo
--
make crp_{,k}q percpu to scale crypto_dispatch().
update locking note later.
--
divide crp_ret_{,k}q by CPU to avoid reordering.
update locking note later.
--
update locking notes of opencrypto(9)
--
Don't disclose uninitialized 32-bit word if cryptodev_session fails.
>From Ilja Van Sprundel.
--
Avert userland-controlled integer overflow.
>From Ilja Van Sprundel.
--
Avoid another userland-controlled integer overflow.
>From Ilja Van Sprundel.
--
refactor: remove glue macros for FreeBSD code.
--
pack crypto_drivers variables to struct and add cacheline_aligned qualifier.
--
use kmem_alloc KPI instead of malloc KPI.
--
use pool_cache(9) instead of pool(9) as they can be called concurrently.


To generate a diff of this commit:
cvs rdiff -u -r1.78.2.2 -r1.78.2.3 src/sys/opencrypto/crypto.c
cvs rdiff -u -r1.34.2.2 -r1.34.2.3 src/sys/opencrypto/cryptodev.h
cvs rdiff -u -r1.8 -r1.8.2.1 src/sys/opencrypto/ocryptodev.c
cvs rdiff -u -r1.28 -r1.28.48.1 src/sys/opencrypto/xform.c
cvs rdiff -u -r1.19 -r1.19.48.1 src/sys/opencrypto/xform.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/opencrypto/crypto.c
diff -u src/sys/opencrypto/crypto.c:1.78.2.2 src/sys/opencrypto/crypto.c:1.78.2.3
--- src/sys/opencrypto/crypto.c:1.78.2.2	Wed Jul  5 20:19:21 2017
+++ src/sys/opencrypto/crypto.c	Sat Aug  5 03:59:21 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.78.2.2 2017/07/05 20:19:21 snj Exp $ */
+/*	$NetBSD: crypto.c,v 1.78.2.3 2017/08/05 03:59:21 snj Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/crypto.c,v 1.4.2.5 2003/02/26 00:14:05 sam Exp $	*/
 /*	$OpenBSD: crypto.c,v 1.41 2002/07/17 23:52:38 art Exp $	*/
 
@@ -53,12 +53,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.78.2.2 2017/07/05 20:19:21 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.78.2.3 2017/08/05 03:59:21 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
 #include <sys/systm.h>
-#include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/pool.h>
 #include <sys/kthread.h>
@@ -67,6 +66,11 @@ __KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1
 #include <sys/intr.h>
 #include <sys/errno.h>
 #include <sys/module.h>
+#include <sys/xcall.h>
+#include <sys/device.h>
+#include <sys/cpu.h>
+#include <sys/percpu.h>
+#include <sys/kmem.h>
 
 #if defined(_KERNEL_OPT)
 #include "opt_ocf.h"
@@ -75,96 +79,127 @@ __KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1
 #include <opencrypto/cryptodev.h>
 #include <opencrypto/xform.h>			/* XXX for M_XDATA */
 
-static kmutex_t crypto_q_mtx;
-static kmutex_t crypto_ret_q_mtx;
-static kcondvar_t cryptoret_cv;
-
-/* below are kludges for residual code wrtitten to FreeBSD interfaces */
-  #define SWI_CRYPTO 17
-  #define register_swi(lvl, fn)  \
-  softint_establish(SOFTINT_NET|SOFTINT_MPSAFE, (void (*)(void *))fn, NULL)
-  #define unregister_swi(lvl, fn)  softint_disestablish(softintr_cookie)
-  #define setsoftcrypto(x)			\
-	do{					\
-		kpreempt_disable();		\
-		softint_schedule(x);		\
-		kpreempt_enable();		\
-	}while(0)
-
-int crypto_ret_q_check(struct cryptop *);
-
 /*
  * Crypto drivers register themselves by allocating a slot in the
  * crypto_drivers table with crypto_get_driverid() and then registering
  * each algorithm they support with crypto_register() and crypto_kregister().
  */
-static kmutex_t crypto_drv_mtx;
 /* Don't directly access crypto_drivers[i], use crypto_checkdriver(i). */
-static	struct cryptocap *crypto_drivers;
-static	int crypto_drivers_num;
-static	void *softintr_cookie;
-static	int crypto_exit_flag;
+static struct {
+	kmutex_t mtx;
+	int num;
+	struct cryptocap *list;
+} crypto_drv __cacheline_aligned;
+#define crypto_drv_mtx		(crypto_drv.mtx)
+#define crypto_drivers_num	(crypto_drv.num)
+#define crypto_drivers		(crypto_drv.list)
+
+static	void *crypto_q_si;
+static	void *crypto_ret_si;
 
 /*
  * There are two queues for crypto requests; one for symmetric (e.g.
  * cipher) operations and one for asymmetric (e.g. MOD) operations.
  * See below for how synchronization is handled.
  */
-static	TAILQ_HEAD(,cryptop) crp_q =		/* request queues */
-		TAILQ_HEAD_INITIALIZER(crp_q);
-static	TAILQ_HEAD(,cryptkop) crp_kq =
-		TAILQ_HEAD_INITIALIZER(crp_kq);
+TAILQ_HEAD(crypto_crp_q, cryptop);
+TAILQ_HEAD(crypto_crp_kq, cryptkop);
+struct crypto_crp_qs {
+	struct crypto_crp_q crp_q;
+	struct crypto_crp_kq crp_kq;
+};
+static percpu_t *crypto_crp_qs_percpu;
 
-/*
- * There are two queues for processing completed crypto requests; one
- * for the symmetric and one for the asymmetric ops.  We only need one
- * but have two to avoid type futzing (cryptop vs. cryptkop).  See below
- * for how synchronization is handled.
- */
-static	TAILQ_HEAD(crprethead, cryptop) crp_ret_q =	/* callback queues */
-		TAILQ_HEAD_INITIALIZER(crp_ret_q);
-static	TAILQ_HEAD(krprethead, cryptkop) crp_ret_kq =
-		TAILQ_HEAD_INITIALIZER(crp_ret_kq);
+static inline struct crypto_crp_qs *
+crypto_get_crp_qs(int *s)
+{
 
-#define DEFINIT_CRYPTO_Q_LEN(name)		\
-	static int crypto_##name##_len = 0
+	KASSERT(s != NULL);
 
-#define DEFINIT_CRYPTO_Q_DROPS(name)		\
-	static int crypto_##name##_drops = 0
+	*s = splsoftnet();
+	return percpu_getref(crypto_crp_qs_percpu);
+}
 
-#define DEFINIT_CRYPTO_Q_MAXLEN(name, defval)		\
-	static int crypto_##name##_maxlen = defval
+static inline void
+crypto_put_crp_qs(int *s)
+{
 
-#define CRYPTO_Q_INC(name)			\
-	do {					\
-		crypto_##name##_len++;		\
-	} while(0);
+	KASSERT(s != NULL);
 
-#define CRYPTO_Q_DEC(name)			\
-	do {					\
-		crypto_##name##_len--;		\
-	} while(0);
+	percpu_putref(crypto_crp_qs_percpu);
+	splx(*s);
+}
 
-#define CRYPTO_Q_INC_DROPS(name)		\
-	do {					\
-		crypto_##name##_drops++;	\
-	} while(0);
+static void
+crypto_crp_q_is_busy_pc(void *p, void *arg, struct cpu_info *ci __unused)
+{
+	struct crypto_crp_qs *qs_pc = p;
+	bool *isempty = arg;
 
-#define CRYPTO_Q_IS_FULL(name)					\
-	(crypto_##name##_maxlen > 0				\
-	    && (crypto_##name##_len > crypto_##name##_maxlen))
+	if (!TAILQ_EMPTY(&qs_pc->crp_q) || !TAILQ_EMPTY(&qs_pc->crp_kq))
+		*isempty = true;
+}
 
-/*
- * current queue length.
- */
-DEFINIT_CRYPTO_Q_LEN(crp_ret_q);
-DEFINIT_CRYPTO_Q_LEN(crp_ret_kq);
+static void
+crypto_crp_qs_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
+{
+	struct crypto_crp_qs *qs = p;
+
+	TAILQ_INIT(&qs->crp_q);
+	TAILQ_INIT(&qs->crp_kq);
+}
 
 /*
- * queue dropped count.
+ * There are two queues for processing completed crypto requests; one
+ * for the symmetric and one for the asymmetric ops.  We only need one
+ * but have two to avoid type futzing (cryptop vs. cryptkop).  See below
+ * for how synchronization is handled.
  */
-DEFINIT_CRYPTO_Q_DROPS(crp_ret_q);
-DEFINIT_CRYPTO_Q_DROPS(crp_ret_kq);
+TAILQ_HEAD(crypto_crp_ret_q, cryptop);
+TAILQ_HEAD(crypto_crp_ret_kq, cryptkop);
+struct crypto_crp_ret_qs {
+	kmutex_t crp_ret_q_mtx;
+	bool crp_ret_q_exit_flag;
+
+	struct crypto_crp_ret_q crp_ret_q;
+	int crp_ret_q_len;
+	int crp_ret_q_maxlen; /* queue length limit. <=0 means unlimited. */
+	int crp_ret_q_drops;
+
+	struct crypto_crp_ret_kq crp_ret_kq;
+	int crp_ret_kq_len;
+	int crp_ret_kq_maxlen; /* queue length limit. <=0 means unlimited. */
+	int crp_ret_kq_drops;
+};
+struct crypto_crp_ret_qs **crypto_crp_ret_qs_list;
+
+
+static inline struct crypto_crp_ret_qs *
+crypto_get_crp_ret_qs(struct cpu_info *ci)
+{
+	u_int cpuid;
+	struct crypto_crp_ret_qs *qs;
+
+	KASSERT(ci != NULL);
+
+	cpuid = cpu_index(ci);
+	qs = crypto_crp_ret_qs_list[cpuid];
+	mutex_enter(&qs->crp_ret_q_mtx);
+	return qs;
+}
+
+static inline void
+crypto_put_crp_ret_qs(struct cpu_info *ci)
+{
+	u_int cpuid;
+	struct crypto_crp_ret_qs *qs;
+
+	KASSERT(ci != NULL);
+
+	cpuid = cpu_index(ci);
+	qs = crypto_crp_ret_qs_list[cpuid];
+	mutex_exit(&qs->crp_ret_q_mtx);
+}
 
 #ifndef CRYPTO_RET_Q_MAXLEN
 #define CRYPTO_RET_Q_MAXLEN 0
@@ -172,57 +207,152 @@ DEFINIT_CRYPTO_Q_DROPS(crp_ret_kq);
 #ifndef CRYPTO_RET_KQ_MAXLEN
 #define CRYPTO_RET_KQ_MAXLEN 0
 #endif
-/*
- * queue length limit.
- * default value is 0. <=0 means unlimited.
- */
-DEFINIT_CRYPTO_Q_MAXLEN(crp_ret_q, CRYPTO_RET_Q_MAXLEN);
-DEFINIT_CRYPTO_Q_MAXLEN(crp_ret_kq, CRYPTO_RET_KQ_MAXLEN);
 
-/*
- * TODO:
- * make percpu
- */
 static int
 sysctl_opencrypto_q_len(SYSCTLFN_ARGS)
 {
-	int error;
+	int error, len = 0;
+	struct sysctlnode node = *rnode;
 
-	error = sysctl_lookup(SYSCTLFN_CALL(rnode));
+	for (int i = 0; i < ncpu; i++) {
+		struct crypto_crp_ret_qs *qs;
+		struct cpu_info *ci = cpu_lookup(i);
+
+		qs = crypto_get_crp_ret_qs(ci);
+		len += qs->crp_ret_q_len;
+		crypto_put_crp_ret_qs(ci);
+	}
+
+	node.sysctl_data = &len;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if (error || newp == NULL)
 		return error;
 
 	return 0;
 }
 
-/*
- * TODO:
- * make percpu
- */
 static int
 sysctl_opencrypto_q_drops(SYSCTLFN_ARGS)
 {
-	int error;
+	int error, drops = 0;
+	struct sysctlnode node = *rnode;
+
+	for (int i = 0; i < ncpu; i++) {
+		struct crypto_crp_ret_qs *qs;
+		struct cpu_info *ci = cpu_lookup(i);
 
-	error = sysctl_lookup(SYSCTLFN_CALL(rnode));
+		qs = crypto_get_crp_ret_qs(ci);
+		drops += qs->crp_ret_q_drops;
+		crypto_put_crp_ret_qs(ci);
+	}
+
+	node.sysctl_data = &drops;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if (error || newp == NULL)
 		return error;
 
 	return 0;
 }
 
-/*
- * need to make percpu?
- */
 static int
 sysctl_opencrypto_q_maxlen(SYSCTLFN_ARGS)
 {
-	int error;
+	int error, maxlen;
+	struct crypto_crp_ret_qs *qs;
+	struct sysctlnode node = *rnode;
+
+	/* each crp_ret_kq_maxlen is the same. */
+	qs = crypto_get_crp_ret_qs(curcpu());
+	maxlen = qs->crp_ret_q_maxlen;
+	crypto_put_crp_ret_qs(curcpu());
+
+	node.sysctl_data = &maxlen;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	for (int i = 0; i < ncpu; i++) {
+		struct cpu_info *ci = cpu_lookup(i);
+
+		qs = crypto_get_crp_ret_qs(ci);
+		qs->crp_ret_q_maxlen = maxlen;
+		crypto_put_crp_ret_qs(ci);
+	}
+
+	return 0;
+}
+
+static int
+sysctl_opencrypto_kq_len(SYSCTLFN_ARGS)
+{
+	int error, len = 0;
+	struct sysctlnode node = *rnode;
+
+	for (int i = 0; i < ncpu; i++) {
+		struct crypto_crp_ret_qs *qs;
+		struct cpu_info *ci = cpu_lookup(i);
+
+		qs = crypto_get_crp_ret_qs(ci);
+		len += qs->crp_ret_kq_len;
+		crypto_put_crp_ret_qs(ci);
+	}
+
+	node.sysctl_data = &len;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	return 0;
+}
+
+static int
+sysctl_opencrypto_kq_drops(SYSCTLFN_ARGS)
+{
+	int error, drops = 0;
+	struct sysctlnode node = *rnode;
+
+	for (int i = 0; i < ncpu; i++) {
+		struct crypto_crp_ret_qs *qs;
+		struct cpu_info *ci = cpu_lookup(i);
+
+		qs = crypto_get_crp_ret_qs(ci);
+		drops += qs->crp_ret_kq_drops;
+		crypto_put_crp_ret_qs(ci);
+	}
+
+	node.sysctl_data = &drops;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	return 0;
+}
+
+static int
+sysctl_opencrypto_kq_maxlen(SYSCTLFN_ARGS)
+{
+	int error, maxlen;
+	struct crypto_crp_ret_qs *qs;
+	struct sysctlnode node = *rnode;
+
+	/* each crp_ret_kq_maxlen is the same. */
+	qs = crypto_get_crp_ret_qs(curcpu());
+	maxlen = qs->crp_ret_kq_maxlen;
+	crypto_put_crp_ret_qs(curcpu());
 
-	error = sysctl_lookup(SYSCTLFN_CALL(rnode));
+	node.sysctl_data = &maxlen;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if (error || newp == NULL)
 		return error;
 
+	for (int i = 0; i < ncpu; i++) {
+		struct cpu_info *ci = cpu_lookup(i);
+
+		qs = crypto_get_crp_ret_qs(ci);
+		qs->crp_ret_kq_maxlen = maxlen;
+		crypto_put_crp_ret_qs(ci);
+	}
+
 	return 0;
 }
 
@@ -230,9 +360,9 @@ sysctl_opencrypto_q_maxlen(SYSCTLFN_ARGS
  * Crypto op and desciptor data structures are allocated
  * from separate private zones(FreeBSD)/pools(netBSD/OpenBSD) .
  */
-struct pool cryptop_pool;
-struct pool cryptodesc_pool;
-struct pool cryptkop_pool;
+static pool_cache_t cryptop_cache;
+static pool_cache_t cryptodesc_cache;
+static pool_cache_t cryptkop_cache;
 
 int	crypto_usercrypto = 1;		/* userland may open /dev/crypto */
 int	crypto_userasymcrypto = 1;	/* userland may do asym crypto reqs */
@@ -296,23 +426,24 @@ sysctl_opencrypto_setup(struct sysctllog
 		       CTLTYPE_INT, "len",
 		       SYSCTL_DESCR("Current queue length"),
 		       sysctl_opencrypto_q_len, 0,
-		       (void *)&crypto_crp_ret_q_len, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 	sysctl_createv(clog, 0, &retqnode, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READONLY,
 		       CTLTYPE_INT, "drops",
 		       SYSCTL_DESCR("Crypto requests dropped due to full ret queue"),
 		       sysctl_opencrypto_q_drops, 0,
-		       (void *)&crypto_crp_ret_q_drops, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 	sysctl_createv(clog, 0, &retqnode, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 		       CTLTYPE_INT, "maxlen",
 		       SYSCTL_DESCR("Maximum allowed queue length"),
 		       sysctl_opencrypto_q_maxlen, 0,
-		       (void *)&crypto_crp_ret_q_maxlen, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 
+
 	sysctl_createv(clog, 0, &ocnode, &retkqnode,
 		       CTLFLAG_PERMANENT,
 		       CTLTYPE_NODE, "crypto_ret_kq",
@@ -323,27 +454,25 @@ sysctl_opencrypto_setup(struct sysctllog
 		       CTLFLAG_PERMANENT|CTLFLAG_READONLY,
 		       CTLTYPE_INT, "len",
 		       SYSCTL_DESCR("Current queue length"),
-		       sysctl_opencrypto_q_len, 0,
-		       (void *)&crypto_crp_ret_kq_len, 0,
+		       sysctl_opencrypto_kq_len, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 	sysctl_createv(clog, 0, &retkqnode, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READONLY,
 		       CTLTYPE_INT, "drops",
 		       SYSCTL_DESCR("Crypto requests dropped due to full ret queue"),
-		       sysctl_opencrypto_q_drops, 0,
-		       (void *)&crypto_crp_ret_kq_drops, 0,
+		       sysctl_opencrypto_kq_drops, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 	sysctl_createv(clog, 0, &retkqnode, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 		       CTLTYPE_INT, "maxlen",
 		       SYSCTL_DESCR("Maximum allowed queue length"),
-		       sysctl_opencrypto_q_maxlen, 0,
-		       (void *)&crypto_crp_ret_kq_maxlen, 0,
+		       sysctl_opencrypto_kq_maxlen, 0,
+		       NULL, 0,
 		       CTL_CREATE, CTL_EOL);
 }
 
-MALLOC_DEFINE(M_CRYPTO_DATA, "crypto", "crypto session records");
-
 /*
  * Synchronization: read carefully, this is non-trivial.
  *
@@ -367,9 +496,8 @@ MALLOC_DEFINE(M_CRYPTO_DATA, "crypto", "
  *
  * This scheme is not intended for SMP machines.
  */
-static	void cryptointr(void);		/* swi thread to dispatch ops */
-static	void cryptoret(void);		/* kernel thread for callbacks*/
-static	struct lwp *cryptothread;
+static	void cryptointr(void *);	/* swi thread to dispatch ops */
+static	void cryptoret_softint(void *);	/* kernel thread for callbacks*/
 static	int crypto_destroy(bool);
 static	int crypto_invoke(struct cryptop *crp, int hint);
 static	int crypto_kinvoke(struct cryptkop *krp, int hint);
@@ -381,6 +509,8 @@ static void crypto_driver_lock(struct cr
 static void crypto_driver_unlock(struct cryptocap *);
 static void crypto_driver_clear(struct cryptocap *);
 
+static int crypto_init_finalize(device_t);
+
 static struct cryptostats cryptostats;
 #ifdef CRYPTO_TIMING
 static	int crypto_timing = 0;
@@ -389,35 +519,95 @@ static	int crypto_timing = 0;
 static struct sysctllog *sysctl_opencrypto_clog;
 
 static int
+crypto_crp_ret_qs_init(void)
+{
+	int i, j;
+
+	crypto_crp_ret_qs_list = kmem_alloc(sizeof(struct crypto_crp_ret_qs *) * ncpu,
+	    KM_NOSLEEP);
+	if (crypto_crp_ret_qs_list == NULL) {
+		printf("crypto_init: crypto_crp_qs_list\n");
+		return ENOMEM;
+	}
+
+	for (i = 0; i < ncpu; i++) {
+		struct crypto_crp_ret_qs *qs;
+		qs = kmem_alloc(sizeof(struct crypto_crp_ret_qs), KM_NOSLEEP);
+		if (qs == NULL)
+			break;
+
+		mutex_init(&qs->crp_ret_q_mtx, MUTEX_DEFAULT, IPL_NET);
+		qs->crp_ret_q_exit_flag = false;
+
+		TAILQ_INIT(&qs->crp_ret_q);
+		qs->crp_ret_q_len = 0;
+		qs->crp_ret_q_maxlen = CRYPTO_RET_Q_MAXLEN;
+		qs->crp_ret_q_drops = 0;
+
+		TAILQ_INIT(&qs->crp_ret_kq);
+		qs->crp_ret_kq_len = 0;
+		qs->crp_ret_kq_maxlen = CRYPTO_RET_KQ_MAXLEN;
+		qs->crp_ret_kq_drops = 0;
+
+		crypto_crp_ret_qs_list[i] = qs;
+	}
+	if (i == ncpu)
+		return 0;
+
+	for (j = 0; j < i; j++) {
+		struct crypto_crp_ret_qs *qs = crypto_crp_ret_qs_list[j];
+
+		mutex_destroy(&qs->crp_ret_q_mtx);
+		kmem_free(qs, sizeof(struct crypto_crp_ret_qs));
+	}
+	kmem_free(crypto_crp_ret_qs_list, sizeof(struct crypto_crp_ret_qs *) * ncpu);
+
+	return ENOMEM;
+}
+
+static int
 crypto_init0(void)
 {
 	int error;
 
 	mutex_init(&crypto_drv_mtx, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&crypto_q_mtx, MUTEX_DEFAULT, IPL_NONE);
-	mutex_init(&crypto_ret_q_mtx, MUTEX_DEFAULT, IPL_NET);
-	cv_init(&cryptoret_cv, "crypto_w");
-	pool_init(&cryptop_pool, sizeof(struct cryptop), 0, 0,  
-		  0, "cryptop", NULL, IPL_NET);
-	pool_init(&cryptodesc_pool, sizeof(struct cryptodesc), 0, 0,
-		  0, "cryptodesc", NULL, IPL_NET);
-	pool_init(&cryptkop_pool, sizeof(struct cryptkop), 0, 0,
-		  0, "cryptkop", NULL, IPL_NET);
+	cryptop_cache = pool_cache_init(sizeof(struct cryptop),
+	    coherency_unit, 0, 0, "cryptop", NULL, IPL_NET, NULL, NULL, NULL);
+	cryptodesc_cache = pool_cache_init(sizeof(struct cryptodesc),
+	    coherency_unit, 0, 0, "cryptdesc", NULL, IPL_NET, NULL, NULL, NULL);
+	cryptkop_cache = pool_cache_init(sizeof(struct cryptkop),
+	    coherency_unit, 0, 0, "cryptkop", NULL, IPL_NET, NULL, NULL, NULL);
 
-	crypto_drivers = malloc(CRYPTO_DRIVERS_INITIAL *
-	    sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT | M_ZERO);
+	crypto_crp_qs_percpu = percpu_alloc(sizeof(struct crypto_crp_qs));
+	percpu_foreach(crypto_crp_qs_percpu, crypto_crp_qs_init_pc, NULL);
+
+	error = crypto_crp_ret_qs_init();
+	if (error) {
+		printf("crypto_init: cannot malloc ret_q list\n");
+		return ENOMEM;
+	}
+
+	crypto_drivers = kmem_zalloc(CRYPTO_DRIVERS_INITIAL *
+	    sizeof(struct cryptocap), KM_NOSLEEP);
 	if (crypto_drivers == NULL) {
 		printf("crypto_init: cannot malloc driver table\n");
 		return ENOMEM;
 	}
 	crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
 
-	softintr_cookie = register_swi(SWI_CRYPTO, cryptointr);
-	error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
-	    (void (*)(void *))cryptoret, NULL, &cryptothread, "cryptoret");
-	if (error) {
-		printf("crypto_init: cannot start cryptoret thread; error %d",
-			error);
+	crypto_q_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE, cryptointr, NULL);
+	if (crypto_q_si == NULL) {
+		printf("crypto_init: cannot establish request queue handler\n");
+		return crypto_destroy(false);
+	}
+
+	/*
+	 * Some encryption devices (such as mvcesa) are attached before
+	 * ipi_sysinit(). That causes an assertion in ipi_register() as
+	 * crypto_ret_si softint uses SOFTINT_RCPU.
+	 */
+	if (config_finalize_register(NULL, crypto_init_finalize) != 0) {
+		printf("crypto_init: cannot register crypto_init_finalize\n");
 		return crypto_destroy(false);
 	}
 
@@ -426,6 +616,17 @@ crypto_init0(void)
 	return 0;
 }
 
+static int
+crypto_init_finalize(device_t self __unused)
+{
+
+	crypto_ret_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE|SOFTINT_RCPU,
+	    &cryptoret_softint, NULL);
+	KASSERT(crypto_ret_si != NULL);
+
+	return 0;
+}
+
 int
 crypto_init(void)
 {
@@ -441,14 +642,14 @@ crypto_destroy(bool exit_kthread)
 
 	if (exit_kthread) {
 		struct cryptocap *cap = NULL;
+		uint64_t where;
+		bool is_busy = false;
 
 		/* if we have any in-progress requests, don't unload */
-		mutex_enter(&crypto_q_mtx);
-		if (!TAILQ_EMPTY(&crp_q) || !TAILQ_EMPTY(&crp_kq)) {
-			mutex_exit(&crypto_q_mtx);
+		percpu_foreach(crypto_crp_qs_percpu, crypto_crp_q_is_busy_pc,
+				   &is_busy);
+		if (is_busy)
 			return EBUSY;
-		}
-		mutex_exit(&crypto_q_mtx);
 		/* FIXME:
 		 * prohibit enqueue to crp_q and crp_kq after here.
 		 */
@@ -468,34 +669,43 @@ crypto_destroy(bool exit_kthread)
 		 * prohibit touch crypto_drivers[] and each element after here.
 		 */
 
-		mutex_spin_enter(&crypto_ret_q_mtx);
-		/* kick the cryptoret thread and wait for it to exit */
-		crypto_exit_flag = 1;
-		cv_signal(&cryptoret_cv);
-
-		while (crypto_exit_flag != 0)
-			cv_wait(&cryptoret_cv, &crypto_ret_q_mtx);
-		mutex_spin_exit(&crypto_ret_q_mtx);
+		/*
+		 * Ensure cryptoret_softint() is never scheduled and then wait
+		 * for last softint_execute().
+		 */
+		for (i = 0; i < ncpu; i++) {
+			struct crypto_crp_ret_qs *qs;
+			struct cpu_info *ci = cpu_lookup(i);
+
+			qs = crypto_get_crp_ret_qs(ci);
+			qs->crp_ret_q_exit_flag = true;
+			crypto_put_crp_ret_qs(ci);
+		}
+		where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
+		xc_wait(where);
 	}
 
 	if (sysctl_opencrypto_clog != NULL)
 		sysctl_teardown(&sysctl_opencrypto_clog);
 
-	unregister_swi(SWI_CRYPTO, cryptointr);
+	if (crypto_ret_si != NULL)
+		softint_disestablish(crypto_ret_si);
+
+	if (crypto_q_si != NULL)
+		softint_disestablish(crypto_q_si);
 
 	mutex_enter(&crypto_drv_mtx);
 	if (crypto_drivers != NULL)
-		free(crypto_drivers, M_CRYPTO_DATA);
+		kmem_free(crypto_drivers,
+		    crypto_drivers_num * sizeof(struct cryptocap));
 	mutex_exit(&crypto_drv_mtx);
 
-	pool_destroy(&cryptop_pool);
-	pool_destroy(&cryptodesc_pool);
-	pool_destroy(&cryptkop_pool);
+	percpu_free(crypto_crp_qs_percpu, sizeof(struct crypto_crp_qs));
 
-	cv_destroy(&cryptoret_cv);
+	pool_cache_destroy(cryptop_cache);
+	pool_cache_destroy(cryptodesc_cache);
+	pool_cache_destroy(cryptkop_cache);
 
-	mutex_destroy(&crypto_ret_q_mtx);
-	mutex_destroy(&crypto_q_mtx);
 	mutex_destroy(&crypto_drv_mtx);
 
 	return 0;
@@ -719,8 +929,8 @@ crypto_get_driverid(u_int32_t flags)
 			return -1;
 		}
 
-		newdrv = malloc(2 * crypto_drivers_num *
-		    sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
+		newdrv = kmem_zalloc(2 * crypto_drivers_num *
+		    sizeof(struct cryptocap), KM_NOSLEEP);
 		if (newdrv == NULL) {
 			mutex_exit(&crypto_drv_mtx);
 			printf("crypto: no space to expand driver table!\n");
@@ -729,10 +939,10 @@ crypto_get_driverid(u_int32_t flags)
 
 		memcpy(newdrv, crypto_drivers,
 		    crypto_drivers_num * sizeof(struct cryptocap));
+		kmem_free(crypto_drivers,
+		    crypto_drivers_num * sizeof(struct cryptocap));
 
 		crypto_drivers_num *= 2;
-
-		free(crypto_drivers, M_CRYPTO_DATA);
 		crypto_drivers = newdrv;
 
 		cap = crypto_checkdriver_uninit(i);
@@ -1057,8 +1267,11 @@ crypto_unblock(u_int32_t driverid, int w
 		cap->cc_kqblocked = 0;
 	}
 	crypto_driver_unlock(cap);
-	if (needwakeup)
-		setsoftcrypto(softintr_cookie);
+	if (needwakeup) {
+		kpreempt_disable();
+		softint_schedule(crypto_q_si);
+		kpreempt_enable();
+	}
 
 	return 0;
 }
@@ -1070,8 +1283,10 @@ crypto_unblock(u_int32_t driverid, int w
 int
 crypto_dispatch(struct cryptop *crp)
 {
-	int result;
+	int result, s;
 	struct cryptocap *cap;
+	struct crypto_crp_qs *crp_qs;
+	struct crypto_crp_q *crp_q;
 
 	KASSERT(crp != NULL);
 
@@ -1094,17 +1309,23 @@ crypto_dispatch(struct cryptop *crp)
 		 *
 		 * don't care list order in batch job.
 		 */
-		mutex_enter(&crypto_q_mtx);
-		wasempty  = TAILQ_EMPTY(&crp_q);
-		TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
-		mutex_exit(&crypto_q_mtx);
-		if (wasempty)
-			setsoftcrypto(softintr_cookie);
+		crp_qs = crypto_get_crp_qs(&s);
+		crp_q = &crp_qs->crp_q;
+		wasempty  = TAILQ_EMPTY(crp_q);
+		TAILQ_INSERT_TAIL(crp_q, crp, crp_next);
+		crypto_put_crp_qs(&s);
+		crp_q = NULL;
+		if (wasempty) {
+			kpreempt_disable();
+			softint_schedule(crypto_q_si);
+			kpreempt_enable();
+		}
 
 		return 0;
 	}
 
-	mutex_enter(&crypto_q_mtx);
+	crp_qs = crypto_get_crp_qs(&s);
+	crp_q = &crp_qs->crp_q;
 	cap = crypto_checkdriver_lock(CRYPTO_SESID2HID(crp->crp_sid));
 	/*
 	 * TODO:
@@ -1116,7 +1337,7 @@ crypto_dispatch(struct cryptop *crp)
 		 * The driver must be detached, so this request will migrate
 		 * to other drivers in cryptointr() later.
 		 */
-		TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
+		TAILQ_INSERT_TAIL(crp_q, crp, crp_next);
 		result = 0;
 		goto out;
 	}
@@ -1127,7 +1348,7 @@ crypto_dispatch(struct cryptop *crp)
 		 * The driver is blocked, just queue the op until
 		 * it unblocks and the swi thread gets kicked.
 		 */
-		TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
+		TAILQ_INSERT_TAIL(crp_q, crp, crp_next);
 		result = 0;
 		goto out;
 	}
@@ -1148,7 +1369,7 @@ crypto_dispatch(struct cryptop *crp)
 		crypto_driver_lock(cap);
 		cap->cc_qblocked = 1;
 		crypto_driver_unlock(cap);
-		TAILQ_INSERT_HEAD(&crp_q, crp, crp_next);
+		TAILQ_INSERT_HEAD(crp_q, crp, crp_next);
 		cryptostats.cs_blocks++;
 
 		/*
@@ -1160,7 +1381,7 @@ crypto_dispatch(struct cryptop *crp)
 	}
 
 out:
-	mutex_exit(&crypto_q_mtx);
+	crypto_put_crp_qs(&s);
 	return result;
 }
 
@@ -1171,14 +1392,17 @@ out:
 int
 crypto_kdispatch(struct cryptkop *krp)
 {
+	int result, s;
 	struct cryptocap *cap;
-	int result;
+	struct crypto_crp_qs *crp_qs;
+	struct crypto_crp_kq *crp_kq;
 
 	KASSERT(krp != NULL);
 
 	cryptostats.cs_kops++;
 
-	mutex_enter(&crypto_q_mtx);
+	crp_qs = crypto_get_crp_qs(&s);
+	crp_kq = &crp_qs->crp_kq;
 	cap = crypto_checkdriver_lock(krp->krp_hid);
 	/*
 	 * TODO:
@@ -1186,7 +1410,7 @@ crypto_kdispatch(struct cryptkop *krp)
 	 * done crypto_unregister(), this migrate operation is not required.
 	 */
 	if (cap == NULL) {
-		TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+		TAILQ_INSERT_TAIL(crp_kq, krp, krp_next);
 		result = 0;
 		goto out;
 	}
@@ -1197,7 +1421,7 @@ crypto_kdispatch(struct cryptkop *krp)
 		 * The driver is blocked, just queue the op until
 		 * it unblocks and the swi thread gets kicked.
 		 */
-		TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+		TAILQ_INSERT_TAIL(crp_kq, krp, krp_next);
 		result = 0;
 		goto out;
 	}
@@ -1213,7 +1437,7 @@ crypto_kdispatch(struct cryptkop *krp)
 		crypto_driver_lock(cap);
 		cap->cc_kqblocked = 1;
 		crypto_driver_unlock(cap);
-		TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
+		TAILQ_INSERT_HEAD(crp_kq, krp, krp_next);
 		cryptostats.cs_kblocks++;
 
 		/*
@@ -1225,7 +1449,7 @@ crypto_kdispatch(struct cryptkop *krp)
 	}
 
 out:
-	mutex_exit(&crypto_q_mtx);
+	crypto_put_crp_qs(&s);
 	return result;
 }
 
@@ -1278,6 +1502,7 @@ crypto_kinvoke(struct cryptkop *krp, int
 		process = cap->cc_kprocess;
 		arg = cap->cc_karg;
 		krp->krp_hid = hid;
+		krp->reqcpu = curcpu();
 		crypto_driver_unlock(cap);
 		error = (*process)(arg, krp, hint);
 	} else {
@@ -1346,6 +1571,7 @@ crypto_invoke(struct cryptop *crp, int h
 
 		process = cap->cc_process;
 		arg = cap->cc_arg;
+		crp->reqcpu = curcpu();
 
 		/*
 		 * Invoke the driver to process the request.
@@ -1398,9 +1624,9 @@ crypto_freereq(struct cryptop *crp)
 
 	while ((crd = crp->crp_desc) != NULL) {
 		crp->crp_desc = crd->crd_next;
-		pool_put(&cryptodesc_pool, crd);
+		pool_cache_put(cryptodesc_cache, crd);
 	}
-	pool_put(&cryptop_pool, crp);
+	pool_cache_put(cryptop_cache, crp);
 }
 
 /*
@@ -1411,24 +1637,29 @@ crypto_getreq(int num)
 {
 	struct cryptodesc *crd;
 	struct cryptop *crp;
+	struct crypto_crp_ret_qs *qs;
 
 	/*
 	 * When crp_ret_q is full, we restrict here to avoid crp_ret_q overflow
 	 * by error callback.
 	 */
-	if (CRYPTO_Q_IS_FULL(crp_ret_q)) {
-		CRYPTO_Q_INC_DROPS(crp_ret_q);
+	qs = crypto_get_crp_ret_qs(curcpu());
+	if (qs->crp_ret_q_maxlen > 0
+	    && qs->crp_ret_q_len > qs->crp_ret_q_maxlen) {
+		qs->crp_ret_q_drops++;
+		crypto_put_crp_ret_qs(curcpu());
 		return NULL;
 	}
+	crypto_put_crp_ret_qs(curcpu());
 
-	crp = pool_get(&cryptop_pool, 0);
+	crp = pool_cache_get(cryptop_cache, 0);
 	if (crp == NULL) {
 		return NULL;
 	}
 	memset(crp, 0, sizeof(struct cryptop));
 
 	while (num--) {
-		crd = pool_get(&cryptodesc_pool, 0);
+		crd = pool_cache_get(cryptodesc_cache, 0);
 		if (crd == NULL) {
 			crypto_freereq(crp);
 			return NULL;
@@ -1460,7 +1691,7 @@ crypto_kfreereq(struct cryptkop *krp)
 		panic("crypto_kfreereq() freeing krp on RETQ\n");
 	}
 
-	pool_put(&cryptkop_pool, krp);
+	pool_cache_put(cryptkop_cache, krp);
 }
 
 /*
@@ -1471,17 +1702,22 @@ struct cryptkop *
 crypto_kgetreq(int num __unused, int prflags)
 {
 	struct cryptkop *krp;
+	struct crypto_crp_ret_qs *qs;
 
 	/*
 	 * When crp_ret_kq is full, we restrict here to avoid crp_ret_kq
 	 * overflow by error callback.
 	 */
-	if (CRYPTO_Q_IS_FULL(crp_ret_kq)) {
-		CRYPTO_Q_INC_DROPS(crp_ret_kq);
+	qs = crypto_get_crp_ret_qs(curcpu());
+	if (qs->crp_ret_kq_maxlen > 0
+	    && qs->crp_ret_kq_len > qs->crp_ret_kq_maxlen) {
+		qs->crp_ret_kq_drops++;
+		crypto_put_crp_ret_qs(curcpu());
 		return NULL;
 	}
+	crypto_put_crp_ret_qs(curcpu());
 
-	krp = pool_get(&cryptkop_pool, prflags);
+	krp = pool_cache_get(cryptkop_cache, prflags);
 	if (krp == NULL) {
 		return NULL;
 	}
@@ -1546,7 +1782,7 @@ crypto_done(struct cryptop *crp)
 			 * If crp->crp_flags & CRYPTO_F_USER and the used
 			 * encryption driver does all the processing in
 			 * the same context, we can skip enqueueing crp_ret_q
-			 * and cv_signal(&cryptoret_cv).
+			 * and softint_schedule(crypto_ret_si).
 			 */
 			DPRINTF("lid[%u]: crp %p CRYPTO_F_USER\n",
 				CRYPTO_SESID2LID(crp->crp_sid), crp);
@@ -1554,21 +1790,24 @@ crypto_done(struct cryptop *crp)
 #endif
 		{
 			int wasempty;
+			struct crypto_crp_ret_qs *qs;
+			struct crypto_crp_ret_q *crp_ret_q;;
 
-			mutex_spin_enter(&crypto_ret_q_mtx);
-			wasempty = TAILQ_EMPTY(&crp_ret_q);
+			qs = crypto_get_crp_ret_qs(crp->reqcpu);
+			crp_ret_q = &qs->crp_ret_q;
+			wasempty = TAILQ_EMPTY(crp_ret_q);
 			DPRINTF("lid[%u]: queueing %p\n",
 				CRYPTO_SESID2LID(crp->crp_sid), crp);
 			crp->crp_flags |= CRYPTO_F_ONRETQ;
-			TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
-			CRYPTO_Q_INC(crp_ret_q);
-			if (wasempty) {
-				DPRINTF("lid[%u]: waking cryptoret, "
+			TAILQ_INSERT_TAIL(crp_ret_q, crp, crp_next);
+			qs->crp_ret_q_len++;
+			if (wasempty && !qs->crp_ret_q_exit_flag) {
+				DPRINTF("lid[%u]: waking cryptoret,"
 					"crp %p hit empty queue\n.",
 					CRYPTO_SESID2LID(crp->crp_sid), crp);
-				cv_signal(&cryptoret_cv);
+				softint_schedule_cpu(crypto_ret_si, crp->reqcpu);
 			}
-			mutex_spin_exit(&crypto_ret_q_mtx);
+			crypto_put_crp_ret_qs(crp->reqcpu);
 		}
 	}
 }
@@ -1597,15 +1836,19 @@ crypto_kdone(struct cryptkop *krp)
 		krp->krp_callback(krp);
 	} else {
 		int wasempty;
+		struct crypto_crp_ret_qs *qs;
+		struct crypto_crp_ret_kq *crp_ret_kq;;
+
+		qs = crypto_get_crp_ret_qs(krp->reqcpu);
+		crp_ret_kq = &qs->crp_ret_kq;
 
-		mutex_spin_enter(&crypto_ret_q_mtx);
-		wasempty = TAILQ_EMPTY(&crp_ret_kq);
+		wasempty = TAILQ_EMPTY(crp_ret_kq);
 		krp->krp_flags |= CRYPTO_F_ONRETQ;
-		TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
-		CRYPTO_Q_INC(crp_ret_kq);
-		if (wasempty)
-			cv_signal(&cryptoret_cv);
-		mutex_spin_exit(&crypto_ret_q_mtx);
+		TAILQ_INSERT_TAIL(crp_ret_kq, krp, krp_next);
+		qs->crp_ret_kq_len++;
+		if (wasempty && !qs->crp_ret_q_exit_flag)
+			softint_schedule_cpu(crypto_ret_si, krp->reqcpu);
+		crypto_put_crp_ret_qs(krp->reqcpu);
 	}
 }
 
@@ -1653,15 +1896,20 @@ unlock:		crypto_driver_unlock(cap);
  * Software interrupt thread to dispatch crypto requests.
  */
 static void
-cryptointr(void)
+cryptointr(void *arg __unused)
 {
 	struct cryptop *crp, *submit, *cnext;
 	struct cryptkop *krp, *knext;
 	struct cryptocap *cap;
-	int result, hint;
+	struct crypto_crp_qs *crp_qs;
+	struct crypto_crp_q *crp_q;
+	struct crypto_crp_kq *crp_kq;
+	int result, hint, s;
 
 	cryptostats.cs_intrs++;
-	mutex_enter(&crypto_q_mtx);
+	crp_qs = crypto_get_crp_qs(&s);
+	crp_q = &crp_qs->crp_q;
+	crp_kq = &crp_qs->crp_kq;
 	do {
 		/*
 		 * Find the first element in the queue that can be
@@ -1670,7 +1918,7 @@ cryptointr(void)
 		 */
 		submit = NULL;
 		hint = 0;
-		TAILQ_FOREACH_SAFE(crp, &crp_q, crp_next, cnext) {
+		TAILQ_FOREACH_SAFE(crp, crp_q, crp_next, cnext) {
 			u_int32_t hid = CRYPTO_SESID2HID(crp->crp_sid);
 			cap = crypto_checkdriver_lock(hid);
 			if (cap == NULL || cap->cc_process == NULL) {
@@ -1716,7 +1964,7 @@ cryptointr(void)
 			break;
 		}
 		if (submit != NULL) {
-			TAILQ_REMOVE(&crp_q, submit, crp_next);
+			TAILQ_REMOVE(crp_q, submit, crp_next);
 			result = crypto_invoke(submit, hint);
 			/* we must take here as the TAILQ op or kinvoke
 			   may need this mutex below.  sigh. */
@@ -1734,18 +1982,18 @@ cryptointr(void)
 				cap = crypto_checkdriver_lock(CRYPTO_SESID2HID(submit->crp_sid));
 				if (cap == NULL) {
 					/* migrate again, sigh... */
-					TAILQ_INSERT_TAIL(&crp_q, submit, crp_next);
+					TAILQ_INSERT_TAIL(crp_q, submit, crp_next);
 				} else {
 					cap->cc_qblocked = 1;
 					crypto_driver_unlock(cap);
-					TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
+					TAILQ_INSERT_HEAD(crp_q, submit, crp_next);
 					cryptostats.cs_blocks++;
 				}
 			}
 		}
 
 		/* As above, but for key ops */
-		TAILQ_FOREACH_SAFE(krp, &crp_kq, krp_next, knext) {
+		TAILQ_FOREACH_SAFE(krp, crp_kq, krp_next, knext) {
 			cap = crypto_checkdriver_lock(krp->krp_hid);
 			if (cap == NULL || cap->cc_kprocess == NULL) {
 				if (cap != NULL)
@@ -1760,7 +2008,7 @@ cryptointr(void)
 			crypto_driver_unlock(cap);
 		}
 		if (krp != NULL) {
-			TAILQ_REMOVE(&crp_kq, krp, krp_next);
+			TAILQ_REMOVE(crp_kq, krp, krp_next);
 			result = crypto_kinvoke(krp, 0);
 			/* the next iteration will want the mutex. :-/ */
 			if (result == ERESTART) {
@@ -1777,63 +2025,54 @@ cryptointr(void)
 				cap = crypto_checkdriver_lock(krp->krp_hid);
 				if (cap == NULL) {
 					/* migrate again, sigh... */
-					TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
+					TAILQ_INSERT_TAIL(crp_kq, krp, krp_next);
 				} else {
 					cap->cc_kqblocked = 1;
 					crypto_driver_unlock(cap);
-					TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
+					TAILQ_INSERT_HEAD(crp_kq, krp, krp_next);
 					cryptostats.cs_kblocks++;
 				}
 			}
 		}
 	} while (submit != NULL || krp != NULL);
-	mutex_exit(&crypto_q_mtx);
+	crypto_put_crp_qs(&s);
 }
 
 /*
- * Kernel thread to do callbacks.
+ * softint handler to do callbacks.
  */
 static void
-cryptoret(void)
+cryptoret_softint(void *arg __unused)
 {
-	struct cryptop *crp;
-	struct cryptkop *krp;
-
-	mutex_spin_enter(&crypto_ret_q_mtx);
+	struct crypto_crp_ret_qs *qs;
+	struct crypto_crp_ret_q *crp_ret_q;;
+	struct crypto_crp_ret_kq *crp_ret_kq;;
+
+	qs = crypto_get_crp_ret_qs(curcpu());
+	crp_ret_q = &qs->crp_ret_q;
+	crp_ret_kq = &qs->crp_ret_kq;
 	for (;;) {
-		crp = TAILQ_FIRST(&crp_ret_q);
+		struct cryptop *crp;
+		struct cryptkop *krp;
+
+		crp = TAILQ_FIRST(crp_ret_q);
 		if (crp != NULL) {
-			TAILQ_REMOVE(&crp_ret_q, crp, crp_next);
-			CRYPTO_Q_DEC(crp_ret_q);
+			TAILQ_REMOVE(crp_ret_q, crp, crp_next);
+			qs->crp_ret_q_len--;
 			crp->crp_flags &= ~CRYPTO_F_ONRETQ;
 		}
-		krp = TAILQ_FIRST(&crp_ret_kq);
+		krp = TAILQ_FIRST(crp_ret_kq);
 		if (krp != NULL) {
-			TAILQ_REMOVE(&crp_ret_kq, krp, krp_next);
-			CRYPTO_Q_DEC(crp_ret_kq);
+			TAILQ_REMOVE(crp_ret_kq, krp, krp_next);
+			qs->crp_ret_q_len--;
 			krp->krp_flags &= ~CRYPTO_F_ONRETQ;
 		}
 
 		/* drop before calling any callbacks. */
-		if (crp == NULL && krp == NULL) {
-
-                        /* Check for the exit condition. */
-			if (crypto_exit_flag != 0) {
-
-        			/* Time to die. */
-				crypto_exit_flag = 0;
-        			cv_broadcast(&cryptoret_cv);
-				mutex_spin_exit(&crypto_ret_q_mtx);
-        			kthread_exit(0);
-			}
-
-			cryptostats.cs_rets++;
-			cv_wait(&cryptoret_cv, &crypto_ret_q_mtx);
-			continue;
-		}
+		if (crp == NULL && krp == NULL)
+			break;
 
-		mutex_spin_exit(&crypto_ret_q_mtx);
-			
+		mutex_spin_exit(&qs->crp_ret_q_mtx);
 		if (crp != NULL) {
 #ifdef CRYPTO_TIMING
 			if (crypto_timing) {
@@ -1855,8 +2094,9 @@ cryptoret(void)
 		if (krp != NULL)
 			krp->krp_callback(krp);
 
-		mutex_spin_enter(&crypto_ret_q_mtx);
+		mutex_spin_enter(&qs->crp_ret_q_mtx);
 	}
+	crypto_put_crp_ret_qs(curcpu());
 }
 
 /* NetBSD module interface */

Index: src/sys/opencrypto/cryptodev.h
diff -u src/sys/opencrypto/cryptodev.h:1.34.2.2 src/sys/opencrypto/cryptodev.h:1.34.2.3
--- src/sys/opencrypto/cryptodev.h:1.34.2.2	Wed Jul  5 20:19:21 2017
+++ src/sys/opencrypto/cryptodev.h	Sat Aug  5 03:59:21 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: cryptodev.h,v 1.34.2.2 2017/07/05 20:19:21 snj Exp $ */
+/*	$NetBSD: cryptodev.h,v 1.34.2.3 2017/08/05 03:59:21 snj Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.2.2.6 2003/07/02 17:04:50 sam Exp $	*/
 /*	$OpenBSD: cryptodev.h,v 1.33 2002/07/17 23:52:39 art Exp $	*/
 
@@ -483,7 +483,11 @@ struct cryptop {
 	void *		crp_opaque;	/* Opaque pointer, passed along */
 	struct cryptodesc *crp_desc;	/* Linked list of processing descriptors */
 
-	int (*crp_callback)(struct cryptop *); /* Callback function */
+	int (*crp_callback)(struct cryptop *); /*
+						* Callback function.
+						* That must not sleep as it is
+						* called in softint context.
+						*/
 
 	void *		crp_mac;
 
@@ -504,6 +508,10 @@ struct cryptop {
 	struct iovec	iovec[1];
 	struct uio	uio;
 	uint32_t	magic;
+	struct cpu_info	*reqcpu;	/*
+					 * save requested CPU to do cryptoret
+					 * softint in the same CPU.
+					 */
 };
 
 #define CRYPTO_BUF_CONTIG	0x0
@@ -530,12 +538,17 @@ struct cryptkop {
 	u_short		krp_oparams;	/* # of output parameters */
 	u_int32_t	krp_hid;
 	struct crparam	krp_param[CRK_MAXPARAM];	/* kvm */
-	int		(*krp_callback)(struct cryptkop *);
+	int		(*krp_callback)(struct cryptkop *);  /*
+							      * Callback function.
+							      * That must not sleep as it is
+							      * called in softint context.
+							      */
 	int		krp_flags;	/* same values as crp_flags */
 	int		krp_devflags;	/* same values as crp_devflags */
 	kcondvar_t	krp_cv;
 	struct fcrypt 	*fcrp;
 	struct crparam	crk_param[CRK_MAXPARAM];
+	struct cpu_info	*reqcpu;
 };
 
 /* Crypto capabilities structure */
@@ -657,12 +670,17 @@ extern int	cuio_getptr(struct uio *, int
  * + crypto_drivers[i] and its all members are protected by
  *   crypto_drivers[i].cc_lock (a spin lock)
  *       spin lock as crypto_unblock() can be called in interrupt context
- * + crp_q and crp_kq are procted by crypto_q_mtx (an adaptive lock)
- * + crp_ret_q, crp_ret_kq and crypto_exit_flag are protected by
- *   crypto_ret_q_mtx (a spin lock)
+ * + percpu'ed crp_q and crp_kq are procted by splsoftnet.
+ * + crp_ret_q, crp_ret_kq and crypto_exit_flag that are members of
+ *   struct crypto_crp_ret_qs are protected by crypto_crp_ret_qs.crp_ret_q_mtx
+ *   (a spin lock)
  *       spin lock as crypto_done() can be called in interrupt context
+ *       NOTE:
+ *       It is not known whether crypto_done()(in interrupt context) is called
+ *       in the same CPU as crypto_dispatch() is called.
+ *       So, struct crypto_crp_ret_qs cannot be percpu(9).
  *
  * Locking order:
- *     - crypto_q_mtx => crypto_drv_mtx => crypto_drivers[i].cc_lock
+ *     - crypto_drv_mtx => crypto_drivers[i].cc_lock
  */
 #endif /* _CRYPTO_CRYPTO_H_ */

Index: src/sys/opencrypto/ocryptodev.c
diff -u src/sys/opencrypto/ocryptodev.c:1.8 src/sys/opencrypto/ocryptodev.c:1.8.2.1
--- src/sys/opencrypto/ocryptodev.c:1.8	Fri Jun  2 09:46:57 2017
+++ src/sys/opencrypto/ocryptodev.c	Sat Aug  5 03:59:21 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ocryptodev.c,v 1.8 2017/06/02 09:46:57 knakahara Exp $ */
+/*	$NetBSD: ocryptodev.c,v 1.8.2.1 2017/08/05 03:59:21 snj Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $	*/
 /*	$OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $	*/
 
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ocryptodev.c,v 1.8 2017/06/02 09:46:57 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ocryptodev.c,v 1.8.2.1 2017/08/05 03:59:21 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -127,6 +127,11 @@ ocryptof_ioctl(struct file *fp, u_long c
 		break;
 	case CIOCNGSESSION:
 		osgop = (struct ocrypt_sgop *)data;
+		if ((osgop->count <= 0) ||
+		    (SIZE_MAX/sizeof(struct osession_n_op) < osgop->count)) {
+			error = EINVAL;
+			break;
+		}
 		osnop = kmem_alloc((osgop->count *
 				  sizeof(struct osession_n_op)), KM_SLEEP);
 		error = copyin(osgop->sessions, osnop, osgop->count *
@@ -159,6 +164,11 @@ mbail:
 		break;
 	case OCIOCNCRYPTM:
 		omop = (struct ocrypt_mop *)data;
+		if ((omop->count <= 0) ||
+		    (SIZE_MAX/sizeof(struct ocrypt_n_op) <= omop->count)) {
+			error = EINVAL;
+			break;
+		}
 		ocnop = kmem_alloc((omop->count * sizeof(struct ocrypt_n_op)),
 		    KM_SLEEP);
 		error = copyin(omop->reqs, ocnop,
@@ -245,8 +255,10 @@ ocryptodev_session(struct fcrypt *fcr, s
 	sop.mackeylen = osop->mackeylen;
 	sop.mackey = osop->mackey;
 	res = cryptodev_session(fcr, &sop);
+	if (res)
+		return res;
 	osop->ses = sop.ses;
-	return res;
+	return 0;
 
 }
 

Index: src/sys/opencrypto/xform.c
diff -u src/sys/opencrypto/xform.c:1.28 src/sys/opencrypto/xform.c:1.28.48.1
--- src/sys/opencrypto/xform.c:1.28	Thu May 26 21:50:03 2011
+++ src/sys/opencrypto/xform.c	Sat Aug  5 03:59:21 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: xform.c,v 1.28 2011/05/26 21:50:03 drochner Exp $ */
+/*	$NetBSD: xform.c,v 1.28.48.1 2017/08/05 03:59:21 snj Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/xform.c,v 1.1.2.1 2002/11/21 23:34:23 sam Exp $	*/
 /*	$OpenBSD: xform.c,v 1.19 2002/08/16 22:47:25 dhartmei Exp $	*/
 
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform.c,v 1.28 2011/05/26 21:50:03 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform.c,v 1.28.48.1 2017/08/05 03:59:21 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -90,169 +90,292 @@ const u_int8_t hmac_opad_buffer[128] = {
 
 /* Encryption instances */
 const struct enc_xform enc_xform_null = {
-	CRYPTO_NULL_CBC, "NULL",
+	.type		= CRYPTO_NULL_CBC,
+	.name		= "NULL",
 	/* NB: blocksize of 4 is to generate a properly aligned ESP header */
-	4, 0, 0, 256 /* 2048 bits, max key */
+	.blocksize	= 4,
+	.ivsize		= 0,
+	.minkey		= 0,
+	.maxkey		= 256, /* 2048 bits, max key */
 };
 
 const struct enc_xform enc_xform_des = {
-	CRYPTO_DES_CBC, "DES",
-	8, 8, 8, 8
+	.type		= CRYPTO_DES_CBC,
+	.name		= "DES",
+	.blocksize	= 8,
+	.ivsize		= 8,
+	.minkey		= 8,
+	.maxkey		= 8,
 };
 
 const struct enc_xform enc_xform_3des = {
-	CRYPTO_3DES_CBC, "3DES",
-	8, 8, 24, 24
+	.type		= CRYPTO_3DES_CBC,
+	.name		= "3DES",
+	.blocksize	= 8,
+	.ivsize		= 8,
+	.minkey		= 24,
+	.maxkey		= 24,
 };
 
 const struct enc_xform enc_xform_blf = {
-	CRYPTO_BLF_CBC, "Blowfish",
-	8, 8, 5, 56 /* 448 bits, max key */
+	.type		= CRYPTO_BLF_CBC,
+	.name		= "Blowfish",
+	.blocksize	= 8,
+	.ivsize		= 8,
+	.minkey		= 5,
+	.maxkey		= 56, /* 448 bits, max key */
 };
 
 const struct enc_xform enc_xform_cast5 = {
-	CRYPTO_CAST_CBC, "CAST-128",
-	8, 8, 5, 16
+	.type		= CRYPTO_CAST_CBC,
+	.name		= "CAST-128",
+	.blocksize	= 8,
+	.ivsize		= 8,
+	.minkey		= 5,
+	.maxkey		= 16,
 };
 
 const struct enc_xform enc_xform_skipjack = {
-	CRYPTO_SKIPJACK_CBC, "Skipjack",
-	8, 8, 10, 10
+	.type		= CRYPTO_SKIPJACK_CBC,
+	.name		= "Skipjack",
+	.blocksize	= 8,
+	.ivsize		= 8,
+	.minkey		= 10,
+	.maxkey		= 10,
 };
 
 const struct enc_xform enc_xform_rijndael128 = {
-	CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
-	16, 16, 16, 32
+	.type		= CRYPTO_RIJNDAEL128_CBC,
+	.name		= "Rijndael-128/AES",
+	.blocksize	= 16,
+	.ivsize		= 16,
+	.minkey		= 16,
+	.maxkey		= 32,
 };
 
 const struct enc_xform enc_xform_arc4 = {
-	CRYPTO_ARC4, "ARC4",
-	1, 0, 1, 32
+	.type		= CRYPTO_ARC4,
+	.name		= "ARC4",
+	.blocksize	= 1,
+	.ivsize		= 0,
+	.minkey		= 1,
+	.maxkey		= 32,
 };
 
 const struct enc_xform enc_xform_camellia = {
-	CRYPTO_CAMELLIA_CBC, "Camellia",
-	16, 16, 8, 32
+	.type		= CRYPTO_CAMELLIA_CBC,
+	.name		= "Camellia",
+	.blocksize	= 16,
+	.ivsize		= 16,
+	.minkey		= 8,
+	.maxkey		= 32,
 };
 
 const struct enc_xform enc_xform_aes_ctr = {
-	CRYPTO_AES_CTR, "AES-CTR",
-	16, 8, 16+4, 32+4
+	.type		= CRYPTO_AES_CTR,
+	.name		= "AES-CTR",
+	.blocksize	= 16,
+	.ivsize		= 8,
+	.minkey		= 16 + 4,
+	.maxkey		= 32 + 4,
 };
 
 const struct enc_xform enc_xform_aes_gcm = {
-	CRYPTO_AES_GCM_16, "AES-GCM",
-	4 /* ??? */, 8, 16+4, 32+4
+	.type		= CRYPTO_AES_GCM_16,
+	.name		= "AES-GCM",
+	.blocksize	= 4, /* ??? */
+	.ivsize		= 8,
+	.minkey		= 16 + 4,
+	.maxkey		= 32 + 4,
 };
 
 const struct enc_xform enc_xform_aes_gmac = {
-	CRYPTO_AES_GMAC, "AES-GMAC",
-	4 /* ??? */, 8, 16+4, 32+4
+	.type		= CRYPTO_AES_GMAC,
+	.name		= "AES-GMAC",
+	.blocksize	= 4, /* ??? */
+	.ivsize		= 8,
+	.minkey		= 16 + 4,
+	.maxkey		= 32 + 4,
 };
 
 /* Authentication instances */
 const struct auth_hash auth_hash_null = {
-	CRYPTO_NULL_HMAC, "NULL-HMAC",
-	0, 0, 12, 64
+	.type		= CRYPTO_NULL_HMAC,
+	.name		= "NULL-HMAC",
+	.keysize	= 0,
+	.hashsize	= 0,
+	.authsize	= 12,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_md5 = {
-	CRYPTO_MD5_HMAC, "HMAC-MD5",
-	16, 16, 16, 64
+	.type		= CRYPTO_MD5_HMAC,
+	.name		= "HMAC-MD5",
+	.keysize	= 16,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_sha1 = {
-	CRYPTO_SHA1_HMAC, "HMAC-SHA1",
-	20, 20, 20, 64
+	.type		= CRYPTO_SHA1_HMAC,
+	.name		= "HMAC-SHA1",
+	.keysize	= 20,
+	.hashsize	= 20,
+	.authsize	= 20,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_ripemd_160 = {
-	CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
-	20, 20, 20, 64
+	.type		= CRYPTO_RIPEMD160_HMAC,
+	.name		= "HMAC-RIPEMD-160",
+	.keysize	= 20,
+	.hashsize	= 20,
+	.authsize	= 20,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_md5_96 = {
-	CRYPTO_MD5_HMAC_96, "HMAC-MD5-96",
-	16, 16, 12, 64
+	.type		= CRYPTO_MD5_HMAC_96,
+	.name		= "HMAC-MD5-96",
+	.keysize	= 16,
+	.hashsize	= 16,
+	.authsize	= 12,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_sha1_96 = {
-	CRYPTO_SHA1_HMAC_96, "HMAC-SHA1-96",
-	20, 20, 12, 64
+	.type		= CRYPTO_SHA1_HMAC_96,
+	.name		= "HMAC-SHA1-96",
+	.keysize	= 20,
+	.hashsize	= 20,
+	.authsize	= 12,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_ripemd_160_96 = {
-	CRYPTO_RIPEMD160_HMAC_96, "HMAC-RIPEMD-160",
-	20, 20, 12, 64
+	.type		= CRYPTO_RIPEMD160_HMAC_96,
+	.name		= "HMAC-RIPEMD-160",
+	.keysize	= 20,
+	.hashsize	= 20,
+	.authsize	= 12,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_key_md5 = {
-	CRYPTO_MD5_KPDK, "Keyed MD5",
-	0, 16, 16, 0
+	.type		= CRYPTO_MD5_KPDK,
+	.name		= "Keyed MD5",
+	.keysize	= 0,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 0,
 };
 
 const struct auth_hash auth_hash_key_sha1 = {
-	CRYPTO_SHA1_KPDK, "Keyed SHA1",
-	0, 20, 20, 0
+	.type		= CRYPTO_SHA1_KPDK,
+	.name		= "Keyed SHA1",
+	.keysize	= 0,
+	.hashsize	= 20,
+	.authsize	= 20,
+	.blocksize	= 0,
 };
 
 const struct auth_hash auth_hash_md5 = {
-	CRYPTO_MD5, "MD5",
-	0, 16, 16, 0
+	.type		= CRYPTO_MD5,
+	.name		= "MD5",
+	.keysize	= 0,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 0,
 };
 
 const struct auth_hash auth_hash_sha1 = {
-	CRYPTO_SHA1, "SHA1",
-	0, 20, 20, 0
+	.type		= CRYPTO_SHA1,
+	.name		= "SHA1",
+	.keysize	= 0,
+	.hashsize	= 20,
+	.authsize	= 20,
+	.blocksize	= 0,
 };
 
 const struct auth_hash auth_hash_hmac_sha2_256 = {
-	CRYPTO_SHA2_256_HMAC, "HMAC-SHA2",
-	32, 32, 16, 64
+	.type		= CRYPTO_SHA2_256_HMAC,
+	.name		= "HMAC-SHA2",
+	.keysize	= 32,
+	.hashsize	= 32,
+	.authsize	= 16,
+	.blocksize	= 64,
 };
 
 const struct auth_hash auth_hash_hmac_sha2_384 = {
-	CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
-	48, 48, 24, 128
+	.type		= CRYPTO_SHA2_384_HMAC,
+	.name		= "HMAC-SHA2-384",
+	.keysize	= 48,
+	.hashsize	= 48,
+	.authsize	= 24,
+	.blocksize	= 128,
 };
 
 const struct auth_hash auth_hash_hmac_sha2_512 = {
-	CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
-	64, 64, 32, 128
+	.type		= CRYPTO_SHA2_512_HMAC,
+	.name		= "HMAC-SHA2-512",
+	.keysize	= 64,
+	.hashsize	= 64,
+	.authsize	= 32,
+	.blocksize	= 128,
 };
 
 const struct auth_hash auth_hash_aes_xcbc_mac_96 = {
-	CRYPTO_AES_XCBC_MAC_96, "AES-XCBC-MAC-96",
-	16, 16, 12, 0
+	.type		= CRYPTO_AES_XCBC_MAC_96,
+	.name		= "AES-XCBC-MAC-96",
+	.keysize	= 16,
+	.hashsize	= 16,
+	.authsize	= 12,
+	.blocksize	= 0,
 };
 
 const struct auth_hash auth_hash_gmac_aes_128 = {
-	CRYPTO_AES_128_GMAC, "GMAC-AES-128",
-	16+4, 16, 16, 16 /* ??? */
+	.type		= CRYPTO_AES_128_GMAC,
+	.name		= "GMAC-AES-128",
+	.keysize	= 16 + 4,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 16, /* ??? */
 };
 
 const struct auth_hash auth_hash_gmac_aes_192 = {
-	CRYPTO_AES_192_GMAC, "GMAC-AES-192",
-	24+4, 16, 16, 16 /* ??? */
+	.type		= CRYPTO_AES_192_GMAC,
+	.name		= "GMAC-AES-192",
+	.keysize	= 24 + 4,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 16, /* ??? */
 };
 
 const struct auth_hash auth_hash_gmac_aes_256 = {
-	CRYPTO_AES_256_GMAC, "GMAC-AES-256",
-	32+4, 16, 16, 16 /* ??? */
+	.type		= CRYPTO_AES_256_GMAC,
+	.name		= "GMAC-AES-256",
+	.keysize	= 32 + 4,
+	.hashsize	= 16,
+	.authsize	= 16,
+	.blocksize	= 16, /* ??? */
 };
 
 /* Compression instance */
 const struct comp_algo comp_algo_deflate = {
-	CRYPTO_DEFLATE_COMP, "Deflate",
-	90
+	.type	= CRYPTO_DEFLATE_COMP,
+	.name	= "Deflate",
+	.minlen	= 90,
 };
 
 const struct comp_algo comp_algo_deflate_nogrow = {
-	CRYPTO_DEFLATE_COMP_NOGROW, "Deflate",
-	90
+	.type	= CRYPTO_DEFLATE_COMP_NOGROW,
+	.name	= "Deflate",
+	.minlen	= 90,
 };
 
 const struct comp_algo comp_algo_gzip = {
-	CRYPTO_GZIP_COMP, "GZIP",
-	90
+	.type	= CRYPTO_GZIP_COMP,
+	.name	= "GZIP",
+	.minlen	= 90,
 };

Index: src/sys/opencrypto/xform.h
diff -u src/sys/opencrypto/xform.h:1.19 src/sys/opencrypto/xform.h:1.19.48.1
--- src/sys/opencrypto/xform.h:1.19	Thu May 26 21:50:03 2011
+++ src/sys/opencrypto/xform.h	Sat Aug  5 03:59:21 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: xform.h,v 1.19 2011/05/26 21:50:03 drochner Exp $ */
+/*	$NetBSD: xform.h,v 1.19.48.1 2017/08/05 03:59:21 snj Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/xform.h,v 1.1.2.1 2002/11/21 23:34:23 sam Exp $	*/
 /*	$OpenBSD: xform.h,v 1.10 2002/04/22 23:10:09 deraadt Exp $	*/
 
@@ -42,8 +42,10 @@ struct auth_hash {
 struct enc_xform {
 	int type;
 	const char *name;
-	u_int16_t blocksize, ivsize;
-	u_int16_t minkey, maxkey;
+	u_int16_t blocksize;
+	u_int16_t ivsize;
+	u_int16_t minkey;
+	u_int16_t maxkey;
 };
 
 struct comp_algo {

Reply via email to