Module Name:    src
Committed By:   knakahara
Date:           Wed Jul 26 06:40:43 UTC 2017

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

Log Message:
make crp_{,k}q percpu to scale crypto_dispatch().

update locking note later.


To generate a diff of this commit:
cvs rdiff -u -r1.94 -r1.95 src/sys/opencrypto/crypto.c

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.94 src/sys/opencrypto/crypto.c:1.95
--- src/sys/opencrypto/crypto.c:1.94	Thu Jul 20 23:07:12 2017
+++ src/sys/opencrypto/crypto.c	Wed Jul 26 06:40:42 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: crypto.c,v 1.94 2017/07/20 23:07:12 knakahara Exp $ */
+/*	$NetBSD: crypto.c,v 1.95 2017/07/26 06:40:42 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.94 2017/07/20 23:07:12 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1.95 2017/07/26 06:40:42 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/reboot.h>
@@ -69,6 +69,7 @@ __KERNEL_RCSID(0, "$NetBSD: crypto.c,v 1
 #include <sys/module.h>
 #include <sys/xcall.h>
 #include <sys/device.h>
+#include <sys/percpu.h>
 
 #if defined(_KERNEL_OPT)
 #include "opt_ocf.h"
@@ -77,7 +78,6 @@ __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;
 
 /* below are kludges for residual code wrtitten to FreeBSD interfaces */
@@ -113,10 +113,52 @@ static	void *crypto_ret_si;
  * 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;
+
+static inline struct crypto_crp_qs *
+crypto_get_crp_qs(int *s)
+{
+
+	KASSERT(s != NULL);
+
+	*s = splsoftnet();
+	return percpu_getref(crypto_crp_qs_percpu);
+}
+
+static inline void
+crypto_put_crp_qs(int *s)
+{
+
+	KASSERT(s != NULL);
+
+	percpu_putref(crypto_crp_qs_percpu);
+	splx(*s);
+}
+
+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;
+
+	if (!TAILQ_EMPTY(&qs_pc->crp_q) || !TAILQ_EMPTY(&qs_pc->crp_kq))
+		*isempty = true;
+}
+
+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);
+}
 
 /*
  * There are two queues for processing completed crypto requests; one
@@ -397,7 +439,6 @@ crypto_init0(void)
 {
 
 	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);
 	pool_init(&cryptop_pool, sizeof(struct cryptop), 0, 0,  
 		  0, "cryptop", NULL, IPL_NET);
@@ -406,6 +447,9 @@ crypto_init0(void)
 	pool_init(&cryptkop_pool, sizeof(struct cryptkop), 0, 0,
 		  0, "cryptkop", NULL, IPL_NET);
 
+	crypto_crp_qs_percpu = percpu_alloc(sizeof(struct crypto_crp_qs));
+	percpu_foreach(crypto_crp_qs_percpu, crypto_crp_qs_init_pc, NULL);
+
 	crypto_drivers = malloc(CRYPTO_DRIVERS_INITIAL *
 	    sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT | M_ZERO);
 	if (crypto_drivers == NULL) {
@@ -462,14 +506,13 @@ 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.
 		 */
@@ -514,12 +557,13 @@ crypto_destroy(bool exit_kthread)
 		free(crypto_drivers, M_CRYPTO_DATA);
 	mutex_exit(&crypto_drv_mtx);
 
+	percpu_free(crypto_crp_qs_percpu, sizeof(struct crypto_crp_qs));
+
 	pool_destroy(&cryptop_pool);
 	pool_destroy(&cryptodesc_pool);
 	pool_destroy(&cryptkop_pool);
 
 	mutex_destroy(&crypto_ret_q_mtx);
-	mutex_destroy(&crypto_q_mtx);
 	mutex_destroy(&crypto_drv_mtx);
 
 	return 0;
@@ -1094,8 +1138,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);
 
@@ -1118,17 +1164,20 @@ 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);
+		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)
 			setsoftcrypto(softintr_cookie);
 
 		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:
@@ -1140,7 +1189,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;
 	}
@@ -1151,7 +1200,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;
 	}
@@ -1172,7 +1221,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++;
 
 		/*
@@ -1184,7 +1233,7 @@ crypto_dispatch(struct cryptop *crp)
 	}
 
 out:
-	mutex_exit(&crypto_q_mtx);
+	crypto_put_crp_qs(&s);
 	return result;
 }
 
@@ -1195,14 +1244,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:
@@ -1210,7 +1262,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;
 	}
@@ -1221,7 +1273,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;
 	}
@@ -1237,7 +1289,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++;
 
 		/*
@@ -1249,7 +1301,7 @@ crypto_kdispatch(struct cryptkop *krp)
 	}
 
 out:
-	mutex_exit(&crypto_q_mtx);
+	crypto_put_crp_qs(&s);
 	return result;
 }
 
@@ -1684,10 +1736,15 @@ cryptointr(void)
 	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
@@ -1696,7 +1753,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) {
@@ -1742,7 +1799,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. */
@@ -1760,18 +1817,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)
@@ -1786,7 +1843,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) {
@@ -1803,17 +1860,17 @@ 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);
 }
 
 /*

Reply via email to