Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi Rework sun8i crypto.



details:   https://anonhg.NetBSD.org/src/rev/333340d20b41
branches:  trunk
changeset: 1010952:333340d20b41
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Jun 13 18:57:54 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 |  781 +++++++++++++++++++++++--------------
 sys/arch/arm/sunxi/sun8i_crypto.h |   17 +-
 2 files changed, 504 insertions(+), 294 deletions(-)

diffs (truncated from 1232 to 300 lines):

diff -r 4ba1a428814e -r 333340d20b41 sys/arch/arm/sunxi/sun8i_crypto.c
--- a/sys/arch/arm/sunxi/sun8i_crypto.c Sat Jun 13 18:54:38 2020 +0000
+++ b/sys/arch/arm/sunxi/sun8i_crypto.c Sat Jun 13 18:57:54 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sun8i_crypto.c,v 1.15 2020/06/13 18:54:38 riastradh Exp $      */
+/*     $NetBSD: sun8i_crypto.c,v 1.16 2020/06/13 18:57:54 riastradh Exp $      */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: sun8i_crypto.c,v 1.15 2020/06/13 18:54:38 riastradh Exp $");
+__KERNEL_RCSID(1, "$NetBSD: sun8i_crypto.c,v 1.16 2020/06/13 18:57:54 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -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);
 }



Home | Main Index | Thread Index | Old Index