Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src-draft/trunk]: src/sys/arch/arm/sunxi Rework sun8i crypto.
details: https://anonhg.NetBSD.org/src-all/rev/ae9adb0e92e3
branches: trunk
changeset: 934481:ae9adb0e92e3
user: Taylor R Campbell <riastradh%NetBSD.org@localhost>
date: Thu Jun 04 03:40:44 2020 +0000
description:
Rework sun8i crypto.
- Preallocate tasks and DMA maps together for now, for 4k transfers.
- Confine setup of the task descriptor to a single function, without
bus_dmamap_t as an input; just use the preallocated DMA maps.
- Take the DMA map part out of sun8i_crypto_buf.
=> Not much left here, just a dmamem segment and kva mapping.
This should make it easier to use with opencrypto.
diffstat:
sys/arch/arm/sunxi/sun8i_crypto.c | 777 +++++++++++++++++++++++--------------
sys/arch/arm/sunxi/sun8i_crypto.h | 15 +-
2 files changed, 501 insertions(+), 291 deletions(-)
diffs (truncated from 1211 to 300 lines):
diff -r 0a81f532e5e4 -r ae9adb0e92e3 sys/arch/arm/sunxi/sun8i_crypto.c
--- a/sys/arch/arm/sunxi/sun8i_crypto.c Fri Jun 12 15:20:48 2020 +0000
+++ b/sys/arch/arm/sunxi/sun8i_crypto.c Thu Jun 04 03:40:44 2020 +0000
@@ -72,7 +72,6 @@
struct sun8i_crypto_buf {
bus_dma_segment_t cb_seg[1];
int cb_nsegs;
- bus_dmamap_t cb_map;
void *cb_kva;
};
@@ -81,6 +80,7 @@
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
bus_dma_tag_t sc_dmat;
+ struct pool_cache *sc_taskpool;
kmutex_t sc_lock;
struct sun8i_crypto_chan {
struct sun8i_crypto_task *cc_task;
@@ -113,13 +113,32 @@
};
struct sun8i_crypto_task {
- struct sun8i_crypto_buf ct_buf;
+ struct sun8i_crypto_buf ct_descbuf;
struct sun8i_crypto_taskdesc *ct_desc;
+ bus_dmamap_t ct_descmap;
+ bus_dmamap_t ct_keymap;
+ bus_dmamap_t ct_ivmap;
+ bus_dmamap_t ct_ctrmap;
+ bus_dmamap_t ct_srcmap;
+ bus_dmamap_t ct_dstmap;
+ uint32_t ct_nbytes;
+ int ct_flags;
+#define TASK_KEY __BIT(0)
+#define TASK_IV __BIT(1)
+#define TASK_CTR __BIT(2)
+#define TASK_SRC __BIT(3)
+#define TASK_BYTES __BIT(4) /* datalen is in bytes, not words */
void (*ct_callback)(struct sun8i_crypto_softc *,
struct sun8i_crypto_task *, void *, int);
void *ct_cookie;
};
+#define SUN8I_CRYPTO_MAXDMASIZE PAGE_SIZE
+#define SUN8I_CRYPTO_MAXDMASEGSIZE PAGE_SIZE
+
+CTASSERT(SUN8I_CRYPTO_MAXDMASIZE <= SUN8I_CRYPTO_MAXDATALEN);
+CTASSERT(SUN8I_CRYPTO_MAXDMASEGSIZE <= SUN8I_CRYPTO_MAXSEGLEN);
+
/*
* Forward declarations
*/
@@ -127,33 +146,27 @@
static int sun8i_crypto_match(device_t, cfdata_t, void *);
static void sun8i_crypto_attach(device_t, device_t, void *);
+static int sun8i_crypto_task_ctor(void *, void *, int);
+static void sun8i_crypto_task_dtor(void *, void *);
static struct sun8i_crypto_task *
sun8i_crypto_task_get(struct sun8i_crypto_softc *,
void (*)(struct sun8i_crypto_softc *,
struct sun8i_crypto_task *, void *, int),
- void *);
+ void *, int);
static void sun8i_crypto_task_put(struct sun8i_crypto_softc *,
struct sun8i_crypto_task *);
-static void sun8i_crypto_task_reset(struct sun8i_crypto_task *);
-static void sun8i_crypto_task_set_key(struct sun8i_crypto_task *,
- bus_dmamap_t);
-static void sun8i_crypto_task_set_iv(struct sun8i_crypto_task *,
- bus_dmamap_t);
-static void sun8i_crypto_task_set_ctr(struct sun8i_crypto_task *,
- bus_dmamap_t);
-static void sun8i_crypto_task_set_input(struct sun8i_crypto_task *,
- bus_dmamap_t);
-static void sun8i_crypto_task_set_output(struct sun8i_crypto_task *,
- bus_dmamap_t);
+static int sun8i_crypto_task_load(struct sun8i_crypto_softc *,
+ struct sun8i_crypto_task *, uint32_t,
+ uint32_t, uint32_t, uint32_t);
+static int sun8i_crypto_task_scatter(struct sun8i_crypto_adrlen *,
+ bus_dmamap_t, uint32_t);
-static void sun8i_crypto_task_scatter(struct sun8i_crypto_adrlen *,
- bus_dmamap_t);
+static int sun8i_crypto_task_load_trng(struct sun8i_crypto_softc *,
+ struct sun8i_crypto_task *, uint32_t);
+static int sun8i_crypto_task_load_aesecb(struct sun8i_crypto_softc *,
+ struct sun8i_crypto_task *, uint32_t, uint32_t, uint32_t);
-static int sun8i_crypto_submit_trng(struct sun8i_crypto_softc *,
- struct sun8i_crypto_task *, uint32_t);
-static int sun8i_crypto_submit_aesecb(struct sun8i_crypto_softc *,
- struct sun8i_crypto_task *, uint32_t, uint32_t, uint32_t);
static int sun8i_crypto_submit(struct sun8i_crypto_softc *,
struct sun8i_crypto_task *);
@@ -165,7 +178,7 @@
int);
static int sun8i_crypto_allocbuf(struct sun8i_crypto_softc *, size_t,
- struct sun8i_crypto_buf *);
+ struct sun8i_crypto_buf *, int);
static void sun8i_crypto_freebuf(struct sun8i_crypto_softc *, size_t,
struct sun8i_crypto_buf *);
@@ -234,6 +247,9 @@
sc->sc_dev = self;
sc->sc_dmat = faa->faa_dmat;
sc->sc_bst = faa->faa_bst;
+ sc->sc_taskpool = pool_cache_init(sizeof(struct sun8i_crypto_task),
+ 0, 0, 0, "sun8icry", NULL, IPL_VM,
+ &sun8i_crypto_task_ctor, &sun8i_crypto_task_dtor, sc);
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
callout_init(&sc->sc_timeout, CALLOUT_MPSAFE);
callout_setfunc(&sc->sc_timeout, &sun8i_crypto_timeout, sc);
@@ -313,102 +329,238 @@
config_interrupts(self, sun8i_crypto_selftest);
}
+static int
+sun8i_crypto_task_ctor(void *cookie, void *vtask, int pflags)
+{
+ struct sun8i_crypto_softc *sc = cookie;
+ struct sun8i_crypto_task *task = vtask;
+ int dmaflags = (pflags & PR_WAITOK) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT;
+ int error;
+
+ /* Create a DMA buffer for the task descriptor. */
+ error = sun8i_crypto_allocbuf(sc, sizeof(*task->ct_desc),
+ &task->ct_descbuf, dmaflags);
+ if (error)
+ goto fail0;
+ task->ct_desc = task->ct_descbuf.cb_kva;
+
+ /* Create a DMA map for the task descriptor and preload it. */
+ error = bus_dmamap_create(sc->sc_dmat, sizeof(*task->ct_desc), 1,
+ sizeof(*task->ct_desc), 0, dmaflags, &task->ct_descmap);
+ if (error)
+ goto fail1;
+ error = bus_dmamap_load(sc->sc_dmat, task->ct_descmap, task->ct_desc,
+ sizeof(*task->ct_desc), NULL, BUS_DMA_WAITOK);
+ if (error)
+ goto fail2;
+
+ /* Create DMA maps for the key, IV, and CTR. */
+ error = bus_dmamap_create(sc->sc_dmat, SUN8I_CRYPTO_MAXKEYBYTES, 1,
+ SUN8I_CRYPTO_MAXKEYBYTES, 0, dmaflags, &task->ct_keymap);
+ if (error)
+ goto fail3;
+ error = bus_dmamap_create(sc->sc_dmat, SUN8I_CRYPTO_MAXIVBYTES, 1,
+ SUN8I_CRYPTO_MAXIVBYTES, 0, dmaflags, &task->ct_ivmap);
+ if (error)
+ goto fail4;
+ error = bus_dmamap_create(sc->sc_dmat, SUN8I_CRYPTO_MAXCTRBYTES, 1,
+ SUN8I_CRYPTO_MAXCTRBYTES, 0, dmaflags, &task->ct_ctrmap);
+ if (error)
+ goto fail5;
+
+ /* Create DMA maps for the src and dst scatter/gather vectors. */
+ error = bus_dmamap_create(sc->sc_dmat, SUN8I_CRYPTO_MAXDMASIZE,
+ SUN8I_CRYPTO_MAXSEGS, SUN8I_CRYPTO_MAXDMASEGSIZE, 0, dmaflags,
+ &task->ct_srcmap);
+ if (error)
+ goto fail6;
+ error = bus_dmamap_create(sc->sc_dmat, SUN8I_CRYPTO_MAXDMASIZE,
+ SUN8I_CRYPTO_MAXSEGS, SUN8I_CRYPTO_MAXDMASEGSIZE, 0, dmaflags,
+ &task->ct_dstmap);
+ if (error)
+ goto fail7;
+
+ /* Success! */
+ return 0;
+
+fail8: __unused
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_dstmap);
+fail7: bus_dmamap_destroy(sc->sc_dmat, task->ct_srcmap);
+fail6: bus_dmamap_destroy(sc->sc_dmat, task->ct_ctrmap);
+fail5: bus_dmamap_destroy(sc->sc_dmat, task->ct_ivmap);
+fail4: bus_dmamap_destroy(sc->sc_dmat, task->ct_keymap);
+fail3: bus_dmamap_unload(sc->sc_dmat, task->ct_descmap);
+fail2: bus_dmamap_destroy(sc->sc_dmat, task->ct_descmap);
+fail1: sun8i_crypto_freebuf(sc, sizeof(*task->ct_desc), &task->ct_descbuf);
+fail0: return error;
+}
+
+static void
+sun8i_crypto_task_dtor(void *cookie, void *vtask)
+{
+ struct sun8i_crypto_softc *sc = cookie;
+ struct sun8i_crypto_task *task = vtask;
+
+ /* XXX Zero the bounce buffers if there are any. */
+
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_dstmap);
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_srcmap);
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_ctrmap);
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_ivmap);
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_keymap);
+ bus_dmamap_unload(sc->sc_dmat, task->ct_descmap);
+ bus_dmamap_destroy(sc->sc_dmat, task->ct_descmap);
+ sun8i_crypto_freebuf(sc, sizeof(*task->ct_desc), &task->ct_descbuf);
+}
+
/*
- * Task allocation
+ * sun8i_crypto_task_get(sc, callback, cookie, pflags)
+ *
+ * Allocate a task that will call callback(sc, task, cookie,
+ * error) when done. pflags is PR_WAITOK or PR_NOWAIT; if
+ * PR_NOWAIT, may fail and return NULL. No further allocation is
+ * needed to submit the task if this succeeds (although task
+ * submission may still fail if all channels are busy).
*/
-
static struct sun8i_crypto_task *
sun8i_crypto_task_get(struct sun8i_crypto_softc *sc,
void (*callback)(struct sun8i_crypto_softc *, struct sun8i_crypto_task *,
void *, int),
- void *cookie)
+ void *cookie, int pflags)
{
struct sun8i_crypto_task *task;
- int error;
-
- /* Allocate a task. */
- task = kmem_zalloc(sizeof(*task), KM_SLEEP);
- /* Allocate a buffer for the descriptor. */
- error = sun8i_crypto_allocbuf(sc, sizeof(*task->ct_desc),
- &task->ct_buf);
- if (error)
- goto fail0;
+ /* Allocate a task, or fail if we can't. */
+ task = pool_cache_get(sc->sc_taskpool, pflags);
+ if (task == NULL)
+ return NULL;
- /* Initialize the task object and return it. */
- task->ct_desc = task->ct_buf.cb_kva;
+ /* Set up flags and the callback. */
+ task->ct_flags = 0;
task->ct_callback = callback;
task->ct_cookie = cookie;
return task;
-
-fail1: __unused
- sun8i_crypto_freebuf(sc, sizeof(*task->ct_desc), &task->ct_buf);
-fail0: kmem_free(task, sizeof(*task));
- return NULL;
}
+/*
+ * sun8i_crypto_task_invalid(sc, task, cookie, error)
+ *
+ * Callback for a task not currently in use, to detect errors.
+ */
+static void
+sun8i_crypto_task_invalid(struct sun8i_crypto_softc *sc,
+ struct sun8i_crypto_task *task, void *cookie, int error)
+{
+ void (*callback)(struct sun8i_crypto_softc *,
+ struct sun8i_crypto_task *, void *, int) = cookie;
+
+ panic("task for callback %p used after free", callback);
+}
+
+/*
+ * sun8i_crypto_task_put(sc, task)
+ *
+ * Free a task obtained with sun8i_crypto_task_get.
+ */
static void
sun8i_crypto_task_put(struct sun8i_crypto_softc *sc,
struct sun8i_crypto_task *task)
{
- sun8i_crypto_freebuf(sc, sizeof(*task->ct_desc), &task->ct_buf);
- kmem_free(task, sizeof(*task));
+ task->ct_cookie = task->ct_callback;
+ task->ct_callback = &sun8i_crypto_task_invalid;
+ pool_cache_put(sc->sc_taskpool, task);
}
/*
- * Task descriptor setup
+ * sun8i_crypto_task_load(sc, task, nbytes, tdqc, tdqs, tdqa)
*
- * WARNING: Task descriptor fields are little-endian, not host-endian.
+ * Set up the task descriptor after the relevant DMA maps have
+ * been loaded for a transfer of nbytes. bus_dmamap_sync matches
+ * sun8i_crypto_chan_done. May fail if input is inadequately
+ * aligned.
+ *
+ * XXX Teach this to fail gracefully if any alignment is wrong.
+ * XXX Teach this to support task chains.
*/
+static int
Home |
Main Index |
Thread Index |
Old Index