Module Name:    src
Committed By:   riastradh
Date:           Sun May 17 00:53:10 UTC 2020

Modified Files:
        src/sys/dev/pci: hifn7751.c hifn7751var.h

Log Message:
Tweak locking and use a pool cache for commands and dmamaps.

This is enough to get the crypto decelerator working in LOCKDEBUG;
previously it would crash the moment you looked at it.


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/sys/dev/pci/hifn7751.c
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/pci/hifn7751var.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/dev/pci/hifn7751.c
diff -u src/sys/dev/pci/hifn7751.c:1.70 src/sys/dev/pci/hifn7751.c:1.71
--- src/sys/dev/pci/hifn7751.c:1.70	Sun May 17 00:52:31 2020
+++ src/sys/dev/pci/hifn7751.c	Sun May 17 00:53:09 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: hifn7751.c,v 1.70 2020/05/17 00:52:31 riastradh Exp $	*/
+/*	$NetBSD: hifn7751.c,v 1.71 2020/05/17 00:53:09 riastradh Exp $	*/
 /*	$OpenBSD: hifn7751.c,v 1.179 2020/01/11 21:34:03 cheloha Exp $	*/
 
 /*
@@ -47,7 +47,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.70 2020/05/17 00:52:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v 1.71 2020/05/17 00:53:09 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -55,10 +55,10 @@ __KERNEL_RCSID(0, "$NetBSD: hifn7751.c,v
 #include <sys/endian.h>
 #include <sys/errno.h>
 #include <sys/kernel.h>
-#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
+#include <sys/pool.h>
 #include <sys/proc.h>
 #include <sys/rndsource.h>
 #include <sys/sha1.h>
@@ -138,6 +138,48 @@ static void	hifn_callback_comp(struct hi
 
 struct hifn_stats hifnstats;
 
+static int
+hifn_cmd_ctor(void *vsc, void *vcmd, int pflags)
+{
+	struct hifn_softc *sc = vsc;
+	struct hifn_command *cmd = vcmd;
+	int bflags = pflags & PR_WAITOK ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT;
+	int error;
+
+	memset(cmd, 0, sizeof(*cmd));
+
+	error = bus_dmamap_create(sc->sc_dmat,
+	    HIFN_MAX_DMALEN, MAX_SCATTER, HIFN_MAX_SEGLEN,
+	    0, bflags, &cmd->src_map);
+	if (error)
+		goto fail0;
+
+	error = bus_dmamap_create(sc->sc_dmat,
+	    HIFN_MAX_SEGLEN*MAX_SCATTER, MAX_SCATTER, HIFN_MAX_SEGLEN,
+	    0, bflags, &cmd->dst_map_alloc);
+	if (error)
+		goto fail1;
+
+	/* Success!  */
+	cmd->dst_map = NULL;
+	return 0;
+
+fail2: __unused
+	bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map_alloc);
+fail1:	bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
+fail0:	return error;
+}
+
+static void
+hifn_cmd_dtor(void *vsc, void *vcmd)
+{
+	struct hifn_softc *sc = vsc;
+	struct hifn_command *cmd = vcmd;
+
+	bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map_alloc);
+	bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
+}
+
 static const struct hifn_product {
 	pci_vendor_id_t		hifn_vendor;
 	pci_product_id_t	hifn_product;
@@ -360,6 +402,11 @@ hifn_attach(device_t parent, device_t se
 		goto fail_intr;
 	}
 
+	sc->sc_cmd_cache = pool_cache_init(sizeof(struct hifn_command),
+	    0, 0, 0, "hifncmd", NULL, IPL_VM,
+	    &hifn_cmd_ctor, &hifn_cmd_dtor, sc);
+	pool_cache_setlowat(sc->sc_cmd_cache, sc->sc_maxses);
+
 	WRITE_REG_0(sc, HIFN_0_PUCNFG,
 	    READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);
 	ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;
@@ -426,7 +473,9 @@ hifn_detach(device_t self, int flags)
 {
 	struct hifn_softc *sc = device_private(self);
 
+	mutex_enter(&sc->sc_mtx);
 	hifn_abort(sc);
+	mutex_exit(&sc->sc_mtx);
 
 	hifn_reset_board(sc, 1);
 
@@ -436,11 +485,11 @@ hifn_detach(device_t self, int flags)
 
 	rnd_detach_source(&sc->sc_rnd_source);
 
-	mutex_enter(&sc->sc_mtx);
 	callout_halt(&sc->sc_tickto, NULL);
 	if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))
 		callout_halt(&sc->sc_rngto, NULL);
-	mutex_exit(&sc->sc_mtx);
+
+	pool_cache_destroy(sc->sc_cmd_cache);
 
 	bus_space_unmap(sc->sc_st1, sc->sc_sh1, sc->sc_iosz1);
 	bus_space_unmap(sc->sc_st0, sc->sc_sh0, sc->sc_iosz0);
@@ -1601,10 +1650,6 @@ hifn_crypto(struct hifn_softc *sc, struc
 	uint32_t cmdlen;
 	int	cmdi, resi, err = 0;
 
-	if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER,
-	    HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map))
-		return (ENOMEM);
-
 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
 		if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->src_map,
 		    cmd->srcu.src_m, BUS_DMA_NOWAIT)) {
@@ -1684,15 +1729,7 @@ hifn_crypto(struct hifn_softc *sc, struc
 			}
 			cmd->dstu.dst_m = m0;
 		}
-	}
-
-	if (cmd->dst_map == NULL) {
-		if (bus_dmamap_create(sc->sc_dmat,
-		    HIFN_MAX_SEGLEN * MAX_SCATTER, MAX_SCATTER,
-		    HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->dst_map)) {
-			err = ENOMEM;
-			goto err_srcmap;
-		}
+		cmd->dst_map = cmd->dst_map_alloc;
 		if (crp->crp_flags & CRYPTO_F_IMBUF) {
 			if (bus_dmamap_load_mbuf(sc->sc_dmat, cmd->dst_map,
 			    cmd->dstu.dst_m, BUS_DMA_NOWAIT)) {
@@ -1840,15 +1877,9 @@ err_dstmap:
 	if (cmd->src_map != cmd->dst_map)
 		bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
 err_dstmap1:
-	if (cmd->src_map != cmd->dst_map)
-		bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 err_srcmap:
-	if (crp->crp_flags & CRYPTO_F_IMBUF &&
-	    cmd->srcu.src_m != cmd->dstu.dst_m)
-		m_freem(cmd->dstu.dst_m);
 	bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
 err_srcmap1:
-	bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 	return (err);
 }
 
@@ -1897,6 +1928,8 @@ hifn_intr(void *arg)
 	uint32_t dmacsr, restart;
 	int i, u;
 
+	mutex_spin_enter(&sc->sc_mtx);
+
 	dmacsr = READ_REG_1(sc, HIFN_1_DMA_CSR);
 
 #ifdef HIFN_DEBUG
@@ -1907,8 +1940,6 @@ hifn_intr(void *arg)
 		       dma->cmdu, dma->srcu, dma->dstu, dma->resu);
 #endif
 
-	mutex_spin_enter(&sc->sc_mtx);
-
 	/* Nothing in the DMA unit interrupted */
 	if ((dmacsr & sc->sc_dmaier) == 0) {
 		mutex_spin_exit(&sc->sc_mtx);
@@ -2143,6 +2174,11 @@ hifn_process(void *arg, struct cryptop *
 		return (EINVAL);
 	}
 
+	if ((cmd = pool_cache_get(sc->sc_cmd_cache, PR_NOWAIT)) == NULL) {
+		hifnstats.hst_nomem++;
+		return (ENOMEM);
+	}
+
 	mutex_spin_enter(&sc->sc_mtx);
 	session = HIFN_SESSION(crp->crp_sid);
 	if (session >= sc->sc_maxses) {
@@ -2150,13 +2186,6 @@ hifn_process(void *arg, struct cryptop *
 		goto errout;
 	}
 
-	cmd = malloc(sizeof(*cmd), M_DEVBUF, M_NOWAIT | M_ZERO);
-	if (cmd == NULL) {
-		hifnstats.hst_nomem++;
-		err = ENOMEM;
-		goto errout;
-	}
-
 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
 		cmd->srcu.src_m = (struct mbuf *)crp->crp_buf;
 		cmd->dstu.dst_m = (struct mbuf *)crp->crp_buf;
@@ -2192,7 +2221,9 @@ hifn_process(void *arg, struct cryptop *
 			enccrd = crd1;
 #ifdef CRYPTO_LZS_COMP
 		} else if (crd1->crd_alg == CRYPTO_LZS_COMP) {
-			return (hifn_compression(sc, crp, cmd));
+			err = hifn_compression(sc, crp, cmd);
+			mutex_spin_exit(&sc->sc_mtx);
+			return err;
 #endif
 		} else {
 			err = EINVAL;
@@ -2358,6 +2389,7 @@ hifn_process(void *arg, struct cryptop *
 
 	err = hifn_crypto(sc, cmd, crp, hint);
 	if (err == 0) {
+		mutex_exit(&sc->sc_mtx);
 		return 0;
 	} else if (err == ERESTART) {
 		/*
@@ -2376,16 +2408,19 @@ hifn_process(void *arg, struct cryptop *
 	}
 
 errout:
-	if (cmd != NULL) {
-		explicit_memset(cmd, 0, sizeof(*cmd));
-		free(cmd, M_DEVBUF);
-	}
 	if (err == EINVAL)
 		hifnstats.hst_invalid++;
 	else
 		hifnstats.hst_nomem++;
 	crp->crp_etype = err;
 	mutex_spin_exit(&sc->sc_mtx);
+	if (cmd != NULL) {
+		if (crp->crp_flags & CRYPTO_F_IMBUF &&
+		    cmd->srcu.src_m != cmd->dstu.dst_m)
+			m_freem(cmd->dstu.dst_m);
+		cmd->dst_map = NULL;
+		pool_cache_put(sc->sc_cmd_cache, cmd);
+	}
 	crypto_done(crp);
 	return (0);
 }
@@ -2398,6 +2433,8 @@ hifn_abort(struct hifn_softc *sc)
 	struct cryptop *crp;
 	int i, u;
 
+	KASSERT(mutex_owned(&sc->sc_mtx));
+
 	i = dma->resk; u = dma->resu;
 	while (u != 0) {
 		cmd = dma->hifn_commands[i];
@@ -2436,15 +2473,14 @@ hifn_abort(struct hifn_softc *sc)
 				 */
 				crp->crp_etype = ENOMEM;
 				bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
-				bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 			} else
 				crp->crp_etype = ENOMEM;
 
 			bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-			bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 
-			explicit_memset(cmd, 0, sizeof(*cmd));
-			free(cmd, M_DEVBUF);
+			cmd->dst_map = NULL;
+			pool_cache_put(sc->sc_cmd_cache, cmd);
+
 			if (crp->crp_etype != EAGAIN)
 				crypto_done(crp);
 		}
@@ -2469,6 +2505,8 @@ hifn_callback(struct hifn_softc *sc, str
 	struct mbuf *m;
 	int totlen, i, u;
 
+	KASSERT(mutex_owned(&sc->sc_mtx));
+
 	if (cmd->src_map == cmd->dst_map)
 		bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 		    0, cmd->src_map->dm_mapsize,
@@ -2559,14 +2597,11 @@ hifn_callback(struct hifn_softc *sc, str
 		}
 	}
 
-	if (cmd->src_map != cmd->dst_map) {
+	if (cmd->src_map != cmd->dst_map)
 		bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
-		bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
-	}
 	bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-	bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
-	explicit_memset(cmd, 0, sizeof(*cmd));
-	free(cmd, M_DEVBUF);
+	cmd->dst_map = NULL;
+	pool_cache_put(sc->sc_cmd_cache, cmd);
 	crypto_done(crp);
 }
 
@@ -2597,18 +2632,6 @@ hifn_compression(struct hifn_softc *sc, 
 		cmd->comp_masks |= HIFN_COMP_CMD_ALG_LZS |
 		    HIFN_COMP_CMD_CLEARHIST;
 
-	if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER,
-	    HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->src_map)) {
-		err = ENOMEM;
-		goto fail;
-	}
-
-	if (bus_dmamap_create(sc->sc_dmat, HIFN_MAX_DMALEN, MAX_SCATTER,
-	    HIFN_MAX_SEGLEN, 0, BUS_DMA_NOWAIT, &cmd->dst_map)) {
-		err = ENOMEM;
-		goto fail;
-	}
-
 	if (crp->crp_flags & CRYPTO_F_IMBUF) {
 		int len;
 
@@ -2683,15 +2706,13 @@ fail:
 	if (cmd->dst_map != NULL) {
 		if (cmd->dst_map->dm_nsegs > 0)
 			bus_dmamap_unload(sc->sc_dmat, cmd->dst_map);
-		bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 	}
 	if (cmd->src_map != NULL) {
 		if (cmd->src_map->dm_nsegs > 0)
 			bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-		bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 	}
-	explicit_memset(cmd, 0, sizeof(*cmd));
-	free(cmd, M_DEVBUF);
+	cmd->dst_map = NULL;
+	pool_cache_put(sc->sc_cmd_cache, cmd);
 	if (err == EINVAL)
 		hifnstats.hst_invalid++;
 	else
@@ -2809,6 +2830,8 @@ hifn_callback_comp(struct hifn_softc *sc
 	uint32_t olen;
 	bus_size_t dstsize;
 
+	KASSERT(mutex_owned(&sc->sc_mtx));
+
 	bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
 	    0, cmd->src_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
 	bus_dmamap_sync(sc->sc_dmat, cmd->dst_map,
@@ -2886,8 +2909,6 @@ hifn_callback_comp(struct hifn_softc *sc
 	crp->crp_olen = olen - cmd->compcrd->crd_skip;
 
 	bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-	bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
-	bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 
 	m = cmd->dstu.dst_m;
 	if (m->m_flags & M_PKTHDR)
@@ -2903,8 +2924,8 @@ hifn_callback_comp(struct hifn_softc *sc
 	}
 
 	m_freem(cmd->srcu.src_m);
-	explicit_memset(cmd, 0, sizeof(*cmd));
-	free(cmd, M_DEVBUF);
+	cmd->dst_map = NULL;
+	pool_cache_put(sc->sc_cmd_cache, cmd);
 	crp->crp_etype = 0;
 	crypto_done(crp);
 	return;
@@ -2913,16 +2934,14 @@ out:
 	if (cmd->dst_map != NULL) {
 		if (cmd->src_map->dm_nsegs != 0)
 			bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-		bus_dmamap_destroy(sc->sc_dmat, cmd->dst_map);
 	}
 	if (cmd->src_map != NULL) {
 		if (cmd->src_map->dm_nsegs != 0)
 			bus_dmamap_unload(sc->sc_dmat, cmd->src_map);
-		bus_dmamap_destroy(sc->sc_dmat, cmd->src_map);
 	}
 	m_freem(cmd->dstu.dst_m);
-	explicit_memset(cmd, 0, sizeof(*cmd));
-	free(cmd, M_DEVBUF);
+	cmd->dst_map = NULL;
+	pool_cache_put(sc->sc_cmd_cache, cmd);
 	crp->crp_etype = err;
 	crypto_done(crp);
 }

Index: src/sys/dev/pci/hifn7751var.h
diff -u src/sys/dev/pci/hifn7751var.h:1.15 src/sys/dev/pci/hifn7751var.h:1.16
--- src/sys/dev/pci/hifn7751var.h:1.15	Sun May 17 00:52:31 2020
+++ src/sys/dev/pci/hifn7751var.h	Sun May 17 00:53:09 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: hifn7751var.h,v 1.15 2020/05/17 00:52:31 riastradh Exp $	*/
+/*	$NetBSD: hifn7751var.h,v 1.16 2020/05/17 00:53:09 riastradh Exp $	*/
 /*	$OpenBSD: hifn7751var.h,v 1.54 2020/01/11 21:34:04 cheloha Exp $	*/
 
 /*
@@ -137,6 +137,7 @@ struct hifn_softc {
 	bus_space_tag_t		sc_st0, sc_st1;
 	bus_size_t		sc_iosz0, sc_iosz1;
 	bus_dma_tag_t		sc_dmat;
+	struct pool_cache	*sc_cmd_cache;
 
 	struct hifn_dma *sc_dma;
 	bus_dmamap_t sc_dmamap;
@@ -275,6 +276,7 @@ struct hifn_command {
 		struct uio *dst_io;
 	} dstu;
 	bus_dmamap_t dst_map;
+	bus_dmamap_t dst_map_alloc;
 
 	struct hifn_softc *softc;
 	struct cryptop *crp;

Reply via email to