Module Name:    src
Committed By:   knakahara
Date:           Tue Jul 18 06:01:37 UTC 2017

Modified Files:
        src/sys/opencrypto: crypto.c cryptodev.h

Log Message:
make cryptoret() context softint to balance dequeuing crypto_ret_q with 
enqueuing it.


To generate a diff of this commit:
cvs rdiff -u -r1.91 -r1.92 src/sys/opencrypto/crypto.c
cvs rdiff -u -r1.37 -r1.38 src/sys/opencrypto/cryptodev.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.91 src/sys/opencrypto/crypto.c:1.92
--- src/sys/opencrypto/crypto.c:1.91	Mon Jun 26 05:34:48 2017
+++ src/sys/opencrypto/crypto.c	Tue Jul 18 06:01:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.91 2017/06/26 05:34:48 knakahara Exp $ */
+/*	$NetBSD: crypto.c,v 1.92 2017/07/18 06:01:36 knakahara 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,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.91 2017/06/26 05:34:48 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.92 2017/07/18 06:01:36 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
@@ -67,6 +67,7 @@ __KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1
 #include <sys/intr.h>
 #include <sys/errno.h>
 #include <sys/module.h>
+#include <sys/xcall.h>
 
 #if defined(_KERNEL_OPT)
 #include "opt_ocf.h"
@@ -77,7 +78,6 @@ __KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1
 
 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
@@ -105,6 +105,8 @@ static	int crypto_drivers_num;
 static	void *softintr_cookie;
 static	int crypto_exit_flag;
 
+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.
@@ -368,8 +370,7 @@ 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 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);
@@ -391,12 +392,10 @@ static struct sysctllog *sysctl_opencryp
 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,
@@ -413,11 +412,15 @@ crypto_init0(void)
 	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);
+	if (softintr_cookie == NULL) {
+		printf("crypto_init: cannot establish request queue handler\n");
+		return crypto_destroy(false);
+	}
+
+	crypto_ret_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE|SOFTINT_RCPU,
+	    &cryptoret_softint, NULL);
+	if (crypto_ret_si == NULL) {
+		printf("crypto_init: cannot establish ret queue handler\n");
 		return crypto_destroy(false);
 	}
 
@@ -441,6 +444,7 @@ crypto_destroy(bool exit_kthread)
 
 	if (exit_kthread) {
 		struct cryptocap *cap = NULL;
+		uint64_t where;
 
 		/* if we have any in-progress requests, don't unload */
 		mutex_enter(&crypto_q_mtx);
@@ -468,20 +472,25 @@ crypto_destroy(bool exit_kthread)
 		 * prohibit touch crypto_drivers[] and each element after here.
 		 */
 
+		/*
+		 * Ensure cryptoret_softint() is never scheduled and then wait
+		 * for last softint_execute().
+		 */
 		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);
+		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 (softintr_cookie != NULL)
+		unregister_swi(SWI_CRYPTO, cryptointr);
 
 	mutex_enter(&crypto_drv_mtx);
 	if (crypto_drivers != NULL)
@@ -492,8 +501,6 @@ crypto_destroy(bool exit_kthread)
 	pool_destroy(&cryptodesc_pool);
 	pool_destroy(&cryptkop_pool);
 
-	cv_destroy(&cryptoret_cv);
-
 	mutex_destroy(&crypto_ret_q_mtx);
 	mutex_destroy(&crypto_q_mtx);
 	mutex_destroy(&crypto_drv_mtx);
@@ -1278,6 +1285,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 +1354,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.
@@ -1546,7 +1555,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);
@@ -1562,11 +1571,11 @@ crypto_done(struct cryptop *crp)
 			crp->crp_flags |= CRYPTO_F_ONRETQ;
 			TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
 			CRYPTO_Q_INC(crp_ret_q);
-			if (wasempty) {
+			if (wasempty && crypto_exit_flag == 0) {
 				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);
 		}
@@ -1603,8 +1612,8 @@ crypto_kdone(struct cryptkop *krp)
 		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);
+		if (wasempty && crypto_exit_flag == 0)
+			softint_schedule_cpu(crypto_ret_si, krp->reqcpu);
 		mutex_spin_exit(&crypto_ret_q_mtx);
 	}
 }
@@ -1791,16 +1800,17 @@ cryptointr(void)
 }
 
 /*
- * 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);
 	for (;;) {
+		struct cryptop *crp;
+		struct cryptkop *krp;
+
 		crp = TAILQ_FIRST(&crp_ret_q);
 		if (crp != NULL) {
 			TAILQ_REMOVE(&crp_ret_q, crp, crp_next);
@@ -1815,25 +1825,10 @@ cryptoret(void)
 		}
 
 		/* 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);
-			
 		if (crp != NULL) {
 #ifdef CRYPTO_TIMING
 			if (crypto_timing) {
@@ -1857,6 +1852,7 @@ cryptoret(void)
 
 		mutex_spin_enter(&crypto_ret_q_mtx);
 	}
+	mutex_spin_exit(&crypto_ret_q_mtx);
 }
 
 /* NetBSD module interface */

Index: src/sys/opencrypto/cryptodev.h
diff -u src/sys/opencrypto/cryptodev.h:1.37 src/sys/opencrypto/cryptodev.h:1.38
--- src/sys/opencrypto/cryptodev.h:1.37	Thu Jun 15 12:41:18 2017
+++ src/sys/opencrypto/cryptodev.h	Tue Jul 18 06:01:36 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: cryptodev.h,v 1.37 2017/06/15 12:41:18 knakahara Exp $ */
+/*	$NetBSD: cryptodev.h,v 1.38 2017/07/18 06:01:36 knakahara 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 */

Reply via email to