Module Name:    src
Committed By:   simonb
Date:           Tue May 12 14:04:50 UTC 2020

Modified Files:
        src/sys/arch/mips/cavium/dev: octeon_rnm.c

Log Message:
Oceton RNG/RNM driver modernisation to fit new entropy world order by
riastradh@, with some tweaks to get working in RNG mode.

XXX TODO: work out how to get raw entropy mode working.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/mips/cavium/dev/octeon_rnm.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/arch/mips/cavium/dev/octeon_rnm.c
diff -u src/sys/arch/mips/cavium/dev/octeon_rnm.c:1.3 src/sys/arch/mips/cavium/dev/octeon_rnm.c:1.4
--- src/sys/arch/mips/cavium/dev/octeon_rnm.c:1.3	Tue May 12 10:37:10 2020
+++ src/sys/arch/mips/cavium/dev/octeon_rnm.c	Tue May 12 14:04:50 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_rnm.c,v 1.3 2020/05/12 10:37:10 simonb Exp $	*/
+/*	$NetBSD: octeon_rnm.c,v 1.4 2020/05/12 14:04:50 simonb Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -27,14 +27,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_rnm.c,v 1.3 2020/05/12 10:37:10 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_rnm.c,v 1.4 2020/05/12 14:04:50 simonb Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
-#include <sys/systm.h>
-#include <sys/sysctl.h>
 #include <sys/kernel.h>
 #include <sys/rndsource.h>
+#include <sys/systm.h>
 
 #include <mips/locore.h>
 #include <mips/cavium/include/iobusvar.h>
@@ -45,26 +44,18 @@ __KERNEL_RCSID(0, "$NetBSD: octeon_rnm.c
 #include <sys/bus.h>
 
 #define RNG_DELAY_CLOCK 91
-#define RNG_DEF_BURST_COUNT 10
-
-int octeon_rnm_burst_count = RNG_DEF_BURST_COUNT;
 
 struct octeon_rnm_softc {
-	device_t sc_dev;
-
 	bus_space_tag_t		sc_bust;
 	bus_space_handle_t	sc_regh;
-
+	kmutex_t		sc_lock;
 	krndsource_t		sc_rndsrc;	/* /dev/random source */
-	struct callout		sc_rngto;	/* rng timeout */
-	int			sc_rnghz;	/* rng poll time */
 };
 
 static int octeon_rnm_match(device_t, struct cfdata *, void *);
 static void octeon_rnm_attach(device_t, device_t, void *);
-static void octeon_rnm_rng(void *);
-static inline uint64_t octeon_rnm_load(struct octeon_rnm_softc *);
-static inline int octeon_rnm_iobdma(struct octeon_rnm_softc *);
+static void octeon_rnm_rng(size_t, void *);
+static uint64_t octeon_rnm_load(struct octeon_rnm_softc *);
 
 CFATTACH_DECL_NEW(octeon_rnm, sizeof(struct octeon_rnm_softc),
     octeon_rnm_match, octeon_rnm_attach, NULL, NULL);
@@ -94,7 +85,6 @@ octeon_rnm_attach(device_t parent, devic
 
 	aprint_normal("\n");
 
-	sc->sc_dev = self;
 	sc->sc_bust = aa->aa_bust;
 	if (bus_space_map(aa->aa_bust, aa->aa_unit->addr, RNM_SIZE,
 	    0, &sc->sc_regh) != 0) {
@@ -110,48 +100,81 @@ octeon_rnm_attach(device_t parent, devic
 		return;
 	}
 
-	bus_space_write_8(sc->sc_bust, sc->sc_regh, RNM_CTL_STATUS_OFFSET,
-	    RNM_CTL_STATUS_RNG_EN | RNM_CTL_STATUS_ENT_EN);
-
-	if (hz >= 100)
-		sc->sc_rnghz = hz / 100;
-	else 
-		sc->sc_rnghz = 1;
-
-	rnd_attach_source(&sc->sc_rndsrc, device_xname(sc->sc_dev),
-	    RND_TYPE_RNG, RND_FLAG_NO_ESTIMATE);
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
 
-	callout_init(&sc->sc_rngto, 0);
+#ifdef notyet
+	/*
+	 * Enable the internal ring oscillator entropy source (ENT),
+	 * but disable the LFSR/SHA-1 engine (RNG) so we get the raw RO
+	 * samples.
+	 *
+	 * XXX simonb
+	 * To access the raw entropy, it looks like this needs to be
+	 * done through the IOBDMA.  Put this in the "Too Hard For Now"
+	 * basket and just use the RNG.
+	 */
+	bus_space_write_8(sc->sc_bust, sc->sc_regh, RNM_CTL_STATUS_OFFSET,
+	    RNM_CTL_STATUS_EXP_ENT | RNM_CTL_STATUS_ENT_EN);
 
-	octeon_rnm_rng(sc);
+	/*
+	 * Once entropy is enabled, 64 bits of raw entropy is available
+	 * every 8 clock cycles.  Wait a microsecond now before the
+	 * random callback is called to much sure random data is
+	 * available.
+	 */
+	delay(1);
+#else
+	/* Enable the LFSR/SHA-1 engine (RNG). */
+	bus_space_write_8(sc->sc_bust, sc->sc_regh, RNM_CTL_STATUS_OFFSET,
+	    RNM_CTL_STATUS_RNG_EN | RNM_CTL_STATUS_ENT_EN);
 
-	aprint_normal("%s: random number generator enabled: %dhz\n",
-	    device_xname(sc->sc_dev), sc->sc_rnghz);
+	/*
+	 * Once entropy is enabled, a 64-bit random number is available
+	 * every 81 clock cycles.  Wait a microsecond now before the
+	 * random callback is called to much sure random data is
+	 * available.
+	 */
+	delay(1);
+#endif
+
+	rndsource_setcb(&sc->sc_rndsrc, octeon_rnm_rng, sc);
+	rnd_attach_source(&sc->sc_rndsrc, device_xname(self), RND_TYPE_RNG,
+	    RND_FLAG_DEFAULT | RND_FLAG_HASCB);
 }
 
 static void
-octeon_rnm_rng(void *vsc)
+octeon_rnm_rng(size_t nbytes, void *vsc)
 {
 	struct octeon_rnm_softc *sc = vsc;
 	uint64_t rn;
 	int i;
 
-	for (i = 0; i < octeon_rnm_burst_count; i++) {
+	/* Prevent concurrent access from emptying the FIFO.  */
+	mutex_enter(&sc->sc_lock);
+	for (i = 0; i < howmany(nbytes, sizeof(rn)); i++) {
 		rn = octeon_rnm_load(sc);
 		rnd_add_data(&sc->sc_rndsrc,
 				&rn, sizeof(rn), sizeof(rn) * NBBY);
 		/*
 		 * XXX
-		 * delay should be over RNG_DELAY_CLOCK cycles at least,
-		 * we need nanodelay() or clkdelay().
+		 *
+		 * If accessing RNG data, the 512 byte FIFO that gets
+		 * 8 bytes of RNG data added every 81 clock cycles.
+		 *
+		 * If accessing raw oscillator entropy, the 512 byte
+		 * FIFO gets 8 bytes of raw entropy added every 8 clock
+		 * cycles.
+		 *
+		 * We should in theory rate limit calls to
+		 * octeon_rnm_load() to observe this limit.  In practice
+		 * we don't appear to call octeon_rnm_load() anywhere
+		 * near that often.
 		 */
-		delay(1);
 	}
-
-	callout_reset(&sc->sc_rngto, sc->sc_rnghz, octeon_rnm_rng, sc);
+	mutex_exit(&sc->sc_lock);
 }
 
-static inline uint64_t
+static uint64_t
 octeon_rnm_load(struct octeon_rnm_softc *sc)
 {
 	uint64_t addr =
@@ -161,45 +184,3 @@ octeon_rnm_load(struct octeon_rnm_softc 
 
 	return octeon_xkphys_read_8(addr);
 }
-
-static inline int
-octeon_rnm_iobdma(struct octeon_rnm_softc *sc)
-{
-
-	/* XXX */
-	return 0;
-}
-
-SYSCTL_SETUP(octeon_rnm_sysctl, "sysctl octeon_rnm subtree setup")
-{
-	int rc, root_num;
-	const struct sysctlnode *node;
-
-	if ( (rc = sysctl_createv(clog, 0, NULL, NULL,
-			CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
-			NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
-		goto err;
-	}
-
-	if ( (rc = sysctl_createv(clog, 0, NULL, &node,
-			CTLFLAG_PERMANENT, CTLTYPE_NODE, "octeon_rnm",
-			SYSCTL_DESCR("octeon_rnm controls"),
-			NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
-		goto err;
-	}
-
-	root_num = node->sysctl_num;
-
-	if ( (rc = sysctl_createv(clog, 0, NULL, NULL,
-			CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-			CTLTYPE_INT, "burst_count",
-			SYSCTL_DESCR("Burst read count per callout"),
-			NULL, 0, &octeon_rnm_burst_count,
-			0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) {
-		goto err;
-	}
-
-	return;
-err:
-	printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
-}

Reply via email to