1b356ddf0SMark Johnston /*- 2b356ddf0SMark Johnston * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3b356ddf0SMark Johnston * 4b356ddf0SMark Johnston * Copyright (c) 2020 Rubicon Communications, LLC (Netgate) 5b356ddf0SMark Johnston * 6b356ddf0SMark Johnston * Redistribution and use in source and binary forms, with or without 7b356ddf0SMark Johnston * modification, are permitted provided that the following conditions 8b356ddf0SMark Johnston * are met: 9b356ddf0SMark Johnston * 1. Redistributions of source code must retain the above copyright 10b356ddf0SMark Johnston * notice, this list of conditions and the following disclaimer. 11b356ddf0SMark Johnston * 2. Redistributions in binary form must reproduce the above copyright 12b356ddf0SMark Johnston * notice, this list of conditions and the following disclaimer in the 13b356ddf0SMark Johnston * documentation and/or other materials provided with the distribution. 14b356ddf0SMark Johnston * 15b356ddf0SMark Johnston * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16b356ddf0SMark Johnston * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17b356ddf0SMark Johnston * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18b356ddf0SMark Johnston * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19b356ddf0SMark Johnston * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20b356ddf0SMark Johnston * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21b356ddf0SMark Johnston * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22b356ddf0SMark Johnston * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23b356ddf0SMark Johnston * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24b356ddf0SMark Johnston * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25b356ddf0SMark Johnston */ 26b356ddf0SMark Johnston 27b356ddf0SMark Johnston #include <sys/cdefs.h> 28b356ddf0SMark Johnston __FBSDID("$FreeBSD$"); 29b356ddf0SMark Johnston 30b356ddf0SMark Johnston #include <sys/param.h> 31b356ddf0SMark Johnston #include <sys/bus.h> 32*0371c3faSMark Johnston #include <sys/counter.h> 33b356ddf0SMark Johnston #include <sys/endian.h> 34b356ddf0SMark Johnston #include <sys/kernel.h> 35b356ddf0SMark Johnston #include <sys/lock.h> 36b356ddf0SMark Johnston #include <sys/malloc.h> 37b356ddf0SMark Johnston #include <sys/module.h> 38b356ddf0SMark Johnston #include <sys/mutex.h> 39b356ddf0SMark Johnston #include <sys/rman.h> 40e934d455SMark Johnston #include <sys/smp.h> 41b356ddf0SMark Johnston #include <sys/sglist.h> 42b356ddf0SMark Johnston #include <sys/sysctl.h> 43b356ddf0SMark Johnston 44b356ddf0SMark Johnston #include <machine/atomic.h> 45b356ddf0SMark Johnston #include <machine/bus.h> 46b356ddf0SMark Johnston 47b356ddf0SMark Johnston #include <crypto/rijndael/rijndael.h> 48b356ddf0SMark Johnston #include <opencrypto/cryptodev.h> 49b356ddf0SMark Johnston #include <opencrypto/xform.h> 50b356ddf0SMark Johnston 51b356ddf0SMark Johnston #include <dev/ofw/ofw_bus.h> 52b356ddf0SMark Johnston #include <dev/ofw/ofw_bus_subr.h> 53b356ddf0SMark Johnston 54b356ddf0SMark Johnston #include "cryptodev_if.h" 55b356ddf0SMark Johnston 56b356ddf0SMark Johnston #include "safexcel_reg.h" 57b356ddf0SMark Johnston #include "safexcel_var.h" 58b356ddf0SMark Johnston 59b356ddf0SMark Johnston static MALLOC_DEFINE(M_SAFEXCEL, "safexcel_req", "safexcel request buffers"); 60b356ddf0SMark Johnston 61b356ddf0SMark Johnston /* 62b356ddf0SMark Johnston * We only support the EIP97 for now. 63b356ddf0SMark Johnston */ 64b356ddf0SMark Johnston static struct ofw_compat_data safexcel_compat[] = { 65b356ddf0SMark Johnston { "inside-secure,safexcel-eip97ies", (uintptr_t)97 }, 66b356ddf0SMark Johnston { "inside-secure,safexcel-eip97", (uintptr_t)97 }, 67b356ddf0SMark Johnston { NULL, 0 } 68b356ddf0SMark Johnston }; 69b356ddf0SMark Johnston 70b356ddf0SMark Johnston const struct safexcel_reg_offsets eip97_regs_offset = { 71b356ddf0SMark Johnston .hia_aic = SAFEXCEL_EIP97_HIA_AIC_BASE, 72b356ddf0SMark Johnston .hia_aic_g = SAFEXCEL_EIP97_HIA_AIC_G_BASE, 73b356ddf0SMark Johnston .hia_aic_r = SAFEXCEL_EIP97_HIA_AIC_R_BASE, 74b356ddf0SMark Johnston .hia_aic_xdr = SAFEXCEL_EIP97_HIA_AIC_xDR_BASE, 75b356ddf0SMark Johnston .hia_dfe = SAFEXCEL_EIP97_HIA_DFE_BASE, 76b356ddf0SMark Johnston .hia_dfe_thr = SAFEXCEL_EIP97_HIA_DFE_THR_BASE, 77b356ddf0SMark Johnston .hia_dse = SAFEXCEL_EIP97_HIA_DSE_BASE, 78b356ddf0SMark Johnston .hia_dse_thr = SAFEXCEL_EIP97_HIA_DSE_THR_BASE, 79b356ddf0SMark Johnston .hia_gen_cfg = SAFEXCEL_EIP97_HIA_GEN_CFG_BASE, 80b356ddf0SMark Johnston .pe = SAFEXCEL_EIP97_PE_BASE, 81b356ddf0SMark Johnston }; 82b356ddf0SMark Johnston 83b356ddf0SMark Johnston const struct safexcel_reg_offsets eip197_regs_offset = { 84b356ddf0SMark Johnston .hia_aic = SAFEXCEL_EIP197_HIA_AIC_BASE, 85b356ddf0SMark Johnston .hia_aic_g = SAFEXCEL_EIP197_HIA_AIC_G_BASE, 86b356ddf0SMark Johnston .hia_aic_r = SAFEXCEL_EIP197_HIA_AIC_R_BASE, 87b356ddf0SMark Johnston .hia_aic_xdr = SAFEXCEL_EIP197_HIA_AIC_xDR_BASE, 88b356ddf0SMark Johnston .hia_dfe = SAFEXCEL_EIP197_HIA_DFE_BASE, 89b356ddf0SMark Johnston .hia_dfe_thr = SAFEXCEL_EIP197_HIA_DFE_THR_BASE, 90b356ddf0SMark Johnston .hia_dse = SAFEXCEL_EIP197_HIA_DSE_BASE, 91b356ddf0SMark Johnston .hia_dse_thr = SAFEXCEL_EIP197_HIA_DSE_THR_BASE, 92b356ddf0SMark Johnston .hia_gen_cfg = SAFEXCEL_EIP197_HIA_GEN_CFG_BASE, 93b356ddf0SMark Johnston .pe = SAFEXCEL_EIP197_PE_BASE, 94b356ddf0SMark Johnston }; 95b356ddf0SMark Johnston 96b356ddf0SMark Johnston static struct safexcel_cmd_descr * 97b356ddf0SMark Johnston safexcel_cmd_descr_next(struct safexcel_cmd_descr_ring *ring) 98b356ddf0SMark Johnston { 99b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 100b356ddf0SMark Johnston 101b356ddf0SMark Johnston if (ring->write == ring->read) 102b356ddf0SMark Johnston return (NULL); 103b356ddf0SMark Johnston cdesc = &ring->desc[ring->read]; 104b356ddf0SMark Johnston ring->read = (ring->read + 1) % SAFEXCEL_RING_SIZE; 105b356ddf0SMark Johnston return (cdesc); 106b356ddf0SMark Johnston } 107b356ddf0SMark Johnston 108b356ddf0SMark Johnston static struct safexcel_res_descr * 109b356ddf0SMark Johnston safexcel_res_descr_next(struct safexcel_res_descr_ring *ring) 110b356ddf0SMark Johnston { 111b356ddf0SMark Johnston struct safexcel_res_descr *rdesc; 112b356ddf0SMark Johnston 113b356ddf0SMark Johnston if (ring->write == ring->read) 114b356ddf0SMark Johnston return (NULL); 115b356ddf0SMark Johnston rdesc = &ring->desc[ring->read]; 116b356ddf0SMark Johnston ring->read = (ring->read + 1) % SAFEXCEL_RING_SIZE; 117b356ddf0SMark Johnston return (rdesc); 118b356ddf0SMark Johnston } 119b356ddf0SMark Johnston 120b356ddf0SMark Johnston static struct safexcel_request * 121b356ddf0SMark Johnston safexcel_alloc_request(struct safexcel_softc *sc, struct safexcel_ring *ring) 122b356ddf0SMark Johnston { 123b356ddf0SMark Johnston struct safexcel_request *req; 124b356ddf0SMark Johnston 125b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 126b356ddf0SMark Johnston 127b356ddf0SMark Johnston if ((req = STAILQ_FIRST(&ring->free_requests)) != NULL) 128b356ddf0SMark Johnston STAILQ_REMOVE_HEAD(&ring->free_requests, link); 129b356ddf0SMark Johnston return (req); 130b356ddf0SMark Johnston } 131b356ddf0SMark Johnston 132b356ddf0SMark Johnston static void 133b356ddf0SMark Johnston safexcel_free_request(struct safexcel_ring *ring, struct safexcel_request *req) 134b356ddf0SMark Johnston { 135b356ddf0SMark Johnston struct safexcel_context_record *ctx; 136b356ddf0SMark Johnston 137b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 138b356ddf0SMark Johnston 139b356ddf0SMark Johnston if (req->dmap_loaded) { 140b356ddf0SMark Johnston bus_dmamap_unload(ring->data_dtag, req->dmap); 141b356ddf0SMark Johnston req->dmap_loaded = false; 142b356ddf0SMark Johnston } 143b356ddf0SMark Johnston ctx = (struct safexcel_context_record *)req->ctx.vaddr; 144b356ddf0SMark Johnston explicit_bzero(ctx->data, sizeof(ctx->data)); 145b356ddf0SMark Johnston explicit_bzero(req->iv, sizeof(req->iv)); 146b356ddf0SMark Johnston STAILQ_INSERT_TAIL(&ring->free_requests, req, link); 147b356ddf0SMark Johnston } 148b356ddf0SMark Johnston 149b356ddf0SMark Johnston static void 150b356ddf0SMark Johnston safexcel_enqueue_request(struct safexcel_softc *sc, struct safexcel_ring *ring, 151b356ddf0SMark Johnston struct safexcel_request *req) 152b356ddf0SMark Johnston { 153b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 154b356ddf0SMark Johnston 155b356ddf0SMark Johnston STAILQ_INSERT_TAIL(&ring->ready_requests, req, link); 156b356ddf0SMark Johnston } 157b356ddf0SMark Johnston 158b356ddf0SMark Johnston static void 159b356ddf0SMark Johnston safexcel_rdr_intr(struct safexcel_softc *sc, int ringidx) 160b356ddf0SMark Johnston { 161b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 162b356ddf0SMark Johnston struct safexcel_res_descr *rdesc; 163b356ddf0SMark Johnston struct safexcel_request *req; 164b356ddf0SMark Johnston struct safexcel_ring *ring; 165092cf8d6SMark Johnston uint32_t blocked, error, i, ncdescs, nrdescs, nreqs; 166b356ddf0SMark Johnston 167092cf8d6SMark Johnston blocked = 0; 168b356ddf0SMark Johnston ring = &sc->sc_ring[ringidx]; 169b356ddf0SMark Johnston 170b356ddf0SMark Johnston mtx_lock(&ring->mtx); 171b356ddf0SMark Johnston nreqs = SAFEXCEL_READ(sc, 172b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ringidx) + SAFEXCEL_HIA_xDR_PROC_COUNT); 173b356ddf0SMark Johnston nreqs >>= SAFEXCEL_xDR_PROC_xD_PKT_OFFSET; 174b356ddf0SMark Johnston nreqs &= SAFEXCEL_xDR_PROC_xD_PKT_MASK; 175b356ddf0SMark Johnston if (nreqs == 0) { 176b356ddf0SMark Johnston SAFEXCEL_DPRINTF(sc, 1, 177b356ddf0SMark Johnston "zero pending requests on ring %d\n", ringidx); 178b356ddf0SMark Johnston goto out; 179b356ddf0SMark Johnston } 180b356ddf0SMark Johnston 181b356ddf0SMark Johnston ring = &sc->sc_ring[ringidx]; 182b356ddf0SMark Johnston bus_dmamap_sync(ring->rdr.dma.tag, ring->rdr.dma.map, 183b356ddf0SMark Johnston BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 184b356ddf0SMark Johnston bus_dmamap_sync(ring->cdr.dma.tag, ring->cdr.dma.map, 185b356ddf0SMark Johnston BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 186b356ddf0SMark Johnston bus_dmamap_sync(ring->dma_atok.tag, ring->dma_atok.map, 187b356ddf0SMark Johnston BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 188b356ddf0SMark Johnston 189b356ddf0SMark Johnston ncdescs = nrdescs = 0; 190b356ddf0SMark Johnston for (i = 0; i < nreqs; i++) { 191b356ddf0SMark Johnston req = STAILQ_FIRST(&ring->queued_requests); 192b356ddf0SMark Johnston KASSERT(req != NULL, ("%s: expected %d pending requests", 193b356ddf0SMark Johnston __func__, nreqs)); 194e934d455SMark Johnston KASSERT(req->ringidx == ringidx, 195e934d455SMark Johnston ("%s: ring index mismatch", __func__)); 196b356ddf0SMark Johnston STAILQ_REMOVE_HEAD(&ring->queued_requests, link); 197b356ddf0SMark Johnston mtx_unlock(&ring->mtx); 198b356ddf0SMark Johnston 199b356ddf0SMark Johnston bus_dmamap_sync(req->ctx.tag, req->ctx.map, 200b356ddf0SMark Johnston BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 201b356ddf0SMark Johnston bus_dmamap_sync(ring->data_dtag, req->dmap, 202b356ddf0SMark Johnston BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 203b356ddf0SMark Johnston 204b356ddf0SMark Johnston ncdescs += req->cdescs; 205b356ddf0SMark Johnston while (req->cdescs-- > 0) { 206b356ddf0SMark Johnston cdesc = safexcel_cmd_descr_next(&ring->cdr); 207b356ddf0SMark Johnston KASSERT(cdesc != NULL, 208b356ddf0SMark Johnston ("%s: missing control descriptor", __func__)); 209b356ddf0SMark Johnston if (req->cdescs == 0) 210b356ddf0SMark Johnston KASSERT(cdesc->last_seg, 211b356ddf0SMark Johnston ("%s: chain is not terminated", __func__)); 212b356ddf0SMark Johnston } 213b356ddf0SMark Johnston nrdescs += req->rdescs; 214b356ddf0SMark Johnston while (req->rdescs-- > 0) { 215b356ddf0SMark Johnston rdesc = safexcel_res_descr_next(&ring->rdr); 216b356ddf0SMark Johnston error = rdesc->result_data.error_code; 217b356ddf0SMark Johnston if (error != 0) { 218b356ddf0SMark Johnston if (error == SAFEXCEL_RESULT_ERR_AUTH_FAILED && 219b356ddf0SMark Johnston req->crp->crp_etype == 0) { 220b356ddf0SMark Johnston req->crp->crp_etype = EBADMSG; 221b356ddf0SMark Johnston } else { 222b356ddf0SMark Johnston SAFEXCEL_DPRINTF(sc, 1, 223b356ddf0SMark Johnston "error code %#x\n", error); 224b356ddf0SMark Johnston req->crp->crp_etype = EIO; 225b356ddf0SMark Johnston } 226b356ddf0SMark Johnston } 227b356ddf0SMark Johnston } 228b356ddf0SMark Johnston 229b356ddf0SMark Johnston crypto_done(req->crp); 230b356ddf0SMark Johnston mtx_lock(&ring->mtx); 231b356ddf0SMark Johnston safexcel_free_request(ring, req); 232b356ddf0SMark Johnston } 233b356ddf0SMark Johnston 234b356ddf0SMark Johnston if (nreqs != 0) { 235b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 236b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ringidx) + SAFEXCEL_HIA_xDR_PROC_COUNT, 237b356ddf0SMark Johnston SAFEXCEL_xDR_PROC_xD_PKT(nreqs) | 238b356ddf0SMark Johnston (sc->sc_config.rd_offset * nrdescs * sizeof(uint32_t))); 239092cf8d6SMark Johnston blocked = ring->blocked; 240092cf8d6SMark Johnston ring->blocked = 0; 241b356ddf0SMark Johnston } 242b356ddf0SMark Johnston out: 243b356ddf0SMark Johnston if (!STAILQ_EMPTY(&ring->queued_requests)) { 244b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 245b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ringidx) + SAFEXCEL_HIA_xDR_THRESH, 246b356ddf0SMark Johnston SAFEXCEL_HIA_CDR_THRESH_PKT_MODE | 1); 247b356ddf0SMark Johnston } 248b356ddf0SMark Johnston mtx_unlock(&ring->mtx); 249092cf8d6SMark Johnston 250092cf8d6SMark Johnston if (blocked) 251092cf8d6SMark Johnston crypto_unblock(sc->sc_cid, blocked); 252b356ddf0SMark Johnston } 253b356ddf0SMark Johnston 254b356ddf0SMark Johnston static void 255b356ddf0SMark Johnston safexcel_ring_intr(void *arg) 256b356ddf0SMark Johnston { 257b356ddf0SMark Johnston struct safexcel_softc *sc; 258b356ddf0SMark Johnston struct safexcel_intr_handle *ih; 259b356ddf0SMark Johnston uint32_t status, stat; 260b356ddf0SMark Johnston int ring; 261092cf8d6SMark Johnston bool rdrpending; 262b356ddf0SMark Johnston 263b356ddf0SMark Johnston ih = arg; 264b356ddf0SMark Johnston sc = ih->sc; 265b356ddf0SMark Johnston ring = ih->ring; 266b356ddf0SMark Johnston 267b356ddf0SMark Johnston status = SAFEXCEL_READ(sc, SAFEXCEL_HIA_AIC_R(sc) + 268b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R_ENABLED_STAT(ring)); 269b356ddf0SMark Johnston /* CDR interrupts */ 270b356ddf0SMark Johnston if (status & SAFEXCEL_CDR_IRQ(ring)) { 271b356ddf0SMark Johnston stat = SAFEXCEL_READ(sc, 272b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, ring) + SAFEXCEL_HIA_xDR_STAT); 273b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 274b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, ring) + SAFEXCEL_HIA_xDR_STAT, 275b356ddf0SMark Johnston stat & SAFEXCEL_CDR_INTR_MASK); 276b356ddf0SMark Johnston } 277b356ddf0SMark Johnston /* RDR interrupts */ 278b356ddf0SMark Johnston rdrpending = false; 279b356ddf0SMark Johnston if (status & SAFEXCEL_RDR_IRQ(ring)) { 280b356ddf0SMark Johnston stat = SAFEXCEL_READ(sc, 281b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ring) + SAFEXCEL_HIA_xDR_STAT); 282b356ddf0SMark Johnston if ((stat & SAFEXCEL_xDR_ERR) == 0) 283b356ddf0SMark Johnston rdrpending = true; 284b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 285b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ring) + SAFEXCEL_HIA_xDR_STAT, 286b356ddf0SMark Johnston stat & SAFEXCEL_RDR_INTR_MASK); 287b356ddf0SMark Johnston } 288b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 289b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R(sc) + SAFEXCEL_HIA_AIC_R_ACK(ring), 290b356ddf0SMark Johnston status); 291b356ddf0SMark Johnston 292b356ddf0SMark Johnston if (rdrpending) 293b356ddf0SMark Johnston safexcel_rdr_intr(sc, ring); 294b356ddf0SMark Johnston } 295b356ddf0SMark Johnston 296b356ddf0SMark Johnston static int 297b356ddf0SMark Johnston safexcel_configure(struct safexcel_softc *sc) 298b356ddf0SMark Johnston { 299b356ddf0SMark Johnston uint32_t i, mask, pemask, reg; 300b356ddf0SMark Johnston device_t dev; 301b356ddf0SMark Johnston 302b356ddf0SMark Johnston if (sc->sc_type == 197) { 303b356ddf0SMark Johnston sc->sc_offsets = eip197_regs_offset; 304b356ddf0SMark Johnston pemask = SAFEXCEL_N_PES_MASK; 305b356ddf0SMark Johnston } else { 306b356ddf0SMark Johnston sc->sc_offsets = eip97_regs_offset; 307b356ddf0SMark Johnston pemask = EIP97_N_PES_MASK; 308b356ddf0SMark Johnston } 309b356ddf0SMark Johnston 310b356ddf0SMark Johnston dev = sc->sc_dev; 311b356ddf0SMark Johnston 312b356ddf0SMark Johnston /* Scan for valid ring interrupt controllers. */ 313b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RING_AIC; i++) { 314b356ddf0SMark Johnston reg = SAFEXCEL_READ(sc, SAFEXCEL_HIA_AIC_R(sc) + 315b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R_VERSION(i)); 316b356ddf0SMark Johnston if (SAFEXCEL_REG_LO16(reg) != EIP201_VERSION_LE) 317b356ddf0SMark Johnston break; 318b356ddf0SMark Johnston } 319b356ddf0SMark Johnston sc->sc_config.aic_rings = i; 320b356ddf0SMark Johnston if (sc->sc_config.aic_rings == 0) 321b356ddf0SMark Johnston return (-1); 322b356ddf0SMark Johnston 323b356ddf0SMark Johnston reg = SAFEXCEL_READ(sc, SAFEXCEL_HIA_AIC_G(sc) + SAFEXCEL_HIA_OPTIONS); 324b356ddf0SMark Johnston /* Check for 64bit addressing. */ 325b356ddf0SMark Johnston if ((reg & SAFEXCEL_OPT_ADDR_64) == 0) 326b356ddf0SMark Johnston return (-1); 327b356ddf0SMark Johnston /* Check alignment constraints (which we do not support). */ 328b356ddf0SMark Johnston if (((reg & SAFEXCEL_OPT_TGT_ALIGN_MASK) >> 329b356ddf0SMark Johnston SAFEXCEL_OPT_TGT_ALIGN_OFFSET) != 0) 330b356ddf0SMark Johnston return (-1); 331b356ddf0SMark Johnston 332b356ddf0SMark Johnston sc->sc_config.hdw = 333b356ddf0SMark Johnston (reg & SAFEXCEL_xDR_HDW_MASK) >> SAFEXCEL_xDR_HDW_OFFSET; 334b356ddf0SMark Johnston mask = (1 << sc->sc_config.hdw) - 1; 335b356ddf0SMark Johnston 336b356ddf0SMark Johnston sc->sc_config.rings = reg & SAFEXCEL_N_RINGS_MASK; 337b356ddf0SMark Johnston /* Limit the number of rings to the number of the AIC Rings. */ 338b356ddf0SMark Johnston sc->sc_config.rings = MIN(sc->sc_config.rings, sc->sc_config.aic_rings); 339b356ddf0SMark Johnston 340b356ddf0SMark Johnston sc->sc_config.pes = (reg & pemask) >> SAFEXCEL_N_PES_OFFSET; 341b356ddf0SMark Johnston 342b356ddf0SMark Johnston sc->sc_config.cd_size = 343b356ddf0SMark Johnston sizeof(struct safexcel_cmd_descr) / sizeof(uint32_t); 344b356ddf0SMark Johnston sc->sc_config.cd_offset = (sc->sc_config.cd_size + mask) & ~mask; 345b356ddf0SMark Johnston 346b356ddf0SMark Johnston sc->sc_config.rd_size = 347b356ddf0SMark Johnston sizeof(struct safexcel_res_descr) / sizeof(uint32_t); 348b356ddf0SMark Johnston sc->sc_config.rd_offset = (sc->sc_config.rd_size + mask) & ~mask; 349b356ddf0SMark Johnston 350b356ddf0SMark Johnston sc->sc_config.atok_offset = 351b356ddf0SMark Johnston (SAFEXCEL_MAX_ATOKENS * sizeof(struct safexcel_instr) + mask) & 352b356ddf0SMark Johnston ~mask; 353b356ddf0SMark Johnston 354b356ddf0SMark Johnston return (0); 355b356ddf0SMark Johnston } 356b356ddf0SMark Johnston 357b356ddf0SMark Johnston static void 358b356ddf0SMark Johnston safexcel_init_hia_bus_access(struct safexcel_softc *sc) 359b356ddf0SMark Johnston { 360b356ddf0SMark Johnston uint32_t version, val; 361b356ddf0SMark Johnston 362b356ddf0SMark Johnston /* Determine endianness and configure byte swap. */ 363b356ddf0SMark Johnston version = SAFEXCEL_READ(sc, 364b356ddf0SMark Johnston SAFEXCEL_HIA_AIC(sc) + SAFEXCEL_HIA_VERSION); 365b356ddf0SMark Johnston val = SAFEXCEL_READ(sc, SAFEXCEL_HIA_AIC(sc) + SAFEXCEL_HIA_MST_CTRL); 366b356ddf0SMark Johnston if (SAFEXCEL_REG_HI16(version) == SAFEXCEL_HIA_VERSION_BE) { 367b356ddf0SMark Johnston val = SAFEXCEL_READ(sc, 368b356ddf0SMark Johnston SAFEXCEL_HIA_AIC(sc) + SAFEXCEL_HIA_MST_CTRL); 369b356ddf0SMark Johnston val = val ^ (SAFEXCEL_MST_CTRL_NO_BYTE_SWAP >> 24); 370b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 371b356ddf0SMark Johnston SAFEXCEL_HIA_AIC(sc) + SAFEXCEL_HIA_MST_CTRL, 372b356ddf0SMark Johnston val); 373b356ddf0SMark Johnston } 374b356ddf0SMark Johnston 375b356ddf0SMark Johnston /* Configure wr/rd cache values. */ 376b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_GEN_CFG(sc) + SAFEXCEL_HIA_MST_CTRL, 377b356ddf0SMark Johnston SAFEXCEL_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) | 378b356ddf0SMark Johnston SAFEXCEL_MST_CTRL_WD_CACHE(WR_CACHE_4BITS)); 379b356ddf0SMark Johnston } 380b356ddf0SMark Johnston 381b356ddf0SMark Johnston static void 382b356ddf0SMark Johnston safexcel_disable_global_interrupts(struct safexcel_softc *sc) 383b356ddf0SMark Johnston { 384b356ddf0SMark Johnston /* Disable and clear pending interrupts. */ 385b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 386b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_G(sc) + SAFEXCEL_HIA_AIC_G_ENABLE_CTRL, 0); 387b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 388b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_G(sc) + SAFEXCEL_HIA_AIC_G_ACK, 389b356ddf0SMark Johnston SAFEXCEL_AIC_G_ACK_ALL_MASK); 390b356ddf0SMark Johnston } 391b356ddf0SMark Johnston 392b356ddf0SMark Johnston /* 393b356ddf0SMark Johnston * Configure the data fetch engine. This component parses command descriptors 394b356ddf0SMark Johnston * and sets up DMA transfers from host memory to the corresponding processing 395b356ddf0SMark Johnston * engine. 396b356ddf0SMark Johnston */ 397b356ddf0SMark Johnston static void 398b356ddf0SMark Johnston safexcel_configure_dfe_engine(struct safexcel_softc *sc, int pe) 399b356ddf0SMark Johnston { 400b356ddf0SMark Johnston /* Reset all DFE threads. */ 401b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 402b356ddf0SMark Johnston SAFEXCEL_HIA_DFE_THR(sc) + SAFEXCEL_HIA_DFE_THR_CTRL(pe), 403b356ddf0SMark Johnston SAFEXCEL_DxE_THR_CTRL_RESET_PE); 404b356ddf0SMark Johnston 405b356ddf0SMark Johnston /* Deassert the DFE reset. */ 406b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 407b356ddf0SMark Johnston SAFEXCEL_HIA_DFE_THR(sc) + SAFEXCEL_HIA_DFE_THR_CTRL(pe), 0); 408b356ddf0SMark Johnston 409b356ddf0SMark Johnston /* DMA transfer size to use. */ 410b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_DFE(sc) + SAFEXCEL_HIA_DFE_CFG(pe), 411b356ddf0SMark Johnston SAFEXCEL_HIA_DFE_CFG_DIS_DEBUG | 412b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MIN_DATA_SIZE(6) | 413b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MAX_DATA_SIZE(9) | 414b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MIN_CTRL_SIZE(6) | 415b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MAX_CTRL_SIZE(7) | 416b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_DATA_CACHE_CTRL(RD_CACHE_3BITS) | 417b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_CTRL_CACHE_CTRL(RD_CACHE_3BITS)); 418b356ddf0SMark Johnston 419b356ddf0SMark Johnston /* Configure the PE DMA transfer thresholds. */ 420b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_PE(sc) + SAFEXCEL_PE_IN_DBUF_THRES(pe), 421b356ddf0SMark Johnston SAFEXCEL_PE_IN_xBUF_THRES_MIN(6) | 422b356ddf0SMark Johnston SAFEXCEL_PE_IN_xBUF_THRES_MAX(9)); 423b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_PE(sc) + SAFEXCEL_PE_IN_TBUF_THRES(pe), 424b356ddf0SMark Johnston SAFEXCEL_PE_IN_xBUF_THRES_MIN(6) | 425b356ddf0SMark Johnston SAFEXCEL_PE_IN_xBUF_THRES_MAX(7)); 426b356ddf0SMark Johnston } 427b356ddf0SMark Johnston 428b356ddf0SMark Johnston /* 429b356ddf0SMark Johnston * Configure the data store engine. This component parses result descriptors 430b356ddf0SMark Johnston * and sets up DMA transfers from the processing engine to host memory. 431b356ddf0SMark Johnston */ 432b356ddf0SMark Johnston static int 433b356ddf0SMark Johnston safexcel_configure_dse(struct safexcel_softc *sc, int pe) 434b356ddf0SMark Johnston { 435b356ddf0SMark Johnston uint32_t val; 436b356ddf0SMark Johnston int count; 437b356ddf0SMark Johnston 438b356ddf0SMark Johnston /* Disable and reset all DSE threads. */ 439b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 440b356ddf0SMark Johnston SAFEXCEL_HIA_DSE_THR(sc) + SAFEXCEL_HIA_DSE_THR_CTRL(pe), 441b356ddf0SMark Johnston SAFEXCEL_DxE_THR_CTRL_RESET_PE); 442b356ddf0SMark Johnston 443b356ddf0SMark Johnston /* Wait for a second for threads to go idle. */ 444b356ddf0SMark Johnston for (count = 0;;) { 445b356ddf0SMark Johnston val = SAFEXCEL_READ(sc, 446b356ddf0SMark Johnston SAFEXCEL_HIA_DSE_THR(sc) + SAFEXCEL_HIA_DSE_THR_STAT(pe)); 447b356ddf0SMark Johnston if ((val & SAFEXCEL_DSE_THR_RDR_ID_MASK) == 448b356ddf0SMark Johnston SAFEXCEL_DSE_THR_RDR_ID_MASK) 449b356ddf0SMark Johnston break; 450b356ddf0SMark Johnston if (count++ > 10000) { 451b356ddf0SMark Johnston device_printf(sc->sc_dev, "DSE reset timeout\n"); 452b356ddf0SMark Johnston return (-1); 453b356ddf0SMark Johnston } 454b356ddf0SMark Johnston DELAY(100); 455b356ddf0SMark Johnston } 456b356ddf0SMark Johnston 457b356ddf0SMark Johnston /* Exit the reset state. */ 458b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 459b356ddf0SMark Johnston SAFEXCEL_HIA_DSE_THR(sc) + SAFEXCEL_HIA_DSE_THR_CTRL(pe), 0); 460b356ddf0SMark Johnston 461b356ddf0SMark Johnston /* DMA transfer size to use */ 462b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_DSE(sc) + SAFEXCEL_HIA_DSE_CFG(pe), 463b356ddf0SMark Johnston SAFEXCEL_HIA_DSE_CFG_DIS_DEBUG | 464b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MIN_DATA_SIZE(7) | 465b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_MAX_DATA_SIZE(8) | 466b356ddf0SMark Johnston SAFEXCEL_HIA_DxE_CFG_DATA_CACHE_CTRL(WR_CACHE_3BITS) | 467b356ddf0SMark Johnston SAFEXCEL_HIA_DSE_CFG_ALLWAYS_BUFFERABLE); 468b356ddf0SMark Johnston 469b356ddf0SMark Johnston /* Configure the procesing engine thresholds */ 470b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 471b356ddf0SMark Johnston SAFEXCEL_PE(sc) + SAFEXCEL_PE_OUT_DBUF_THRES(pe), 472b356ddf0SMark Johnston SAFEXCEL_PE_OUT_DBUF_THRES_MIN(7) | 473b356ddf0SMark Johnston SAFEXCEL_PE_OUT_DBUF_THRES_MAX(8)); 474b356ddf0SMark Johnston 475b356ddf0SMark Johnston return (0); 476b356ddf0SMark Johnston } 477b356ddf0SMark Johnston 478b356ddf0SMark Johnston static void 479b356ddf0SMark Johnston safexcel_hw_prepare_rings(struct safexcel_softc *sc) 480b356ddf0SMark Johnston { 481b356ddf0SMark Johnston int i; 482b356ddf0SMark Johnston 483b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 484b356ddf0SMark Johnston /* 485b356ddf0SMark Johnston * Command descriptors. 486b356ddf0SMark Johnston */ 487b356ddf0SMark Johnston 488b356ddf0SMark Johnston /* Clear interrupts for this ring. */ 489b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 490b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R(sc) + SAFEXCEL_HIA_AIC_R_ENABLE_CLR(i), 491b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R_ENABLE_CLR_ALL_MASK); 492b356ddf0SMark Johnston 493b356ddf0SMark Johnston /* Disable external triggering. */ 494b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 495b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_CFG, 0); 496b356ddf0SMark Johnston 497b356ddf0SMark Johnston /* Clear the pending prepared counter. */ 498b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 499b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_COUNT, 500b356ddf0SMark Johnston SAFEXCEL_xDR_PREP_CLR_COUNT); 501b356ddf0SMark Johnston 502b356ddf0SMark Johnston /* Clear the pending processed counter. */ 503b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 504b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_COUNT, 505b356ddf0SMark Johnston SAFEXCEL_xDR_PROC_CLR_COUNT); 506b356ddf0SMark Johnston 507b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 508b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_PNTR, 0); 509b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 510b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_PNTR, 0); 511b356ddf0SMark Johnston 512b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 513b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_RING_SIZE, 514b356ddf0SMark Johnston SAFEXCEL_RING_SIZE * sc->sc_config.cd_offset * 515b356ddf0SMark Johnston sizeof(uint32_t)); 516b356ddf0SMark Johnston 517b356ddf0SMark Johnston /* 518b356ddf0SMark Johnston * Result descriptors. 519b356ddf0SMark Johnston */ 520b356ddf0SMark Johnston 521b356ddf0SMark Johnston /* Disable external triggering. */ 522b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 523b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_CFG, 0); 524b356ddf0SMark Johnston 525b356ddf0SMark Johnston /* Clear the pending prepared counter. */ 526b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 527b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_COUNT, 528b356ddf0SMark Johnston SAFEXCEL_xDR_PREP_CLR_COUNT); 529b356ddf0SMark Johnston 530b356ddf0SMark Johnston /* Clear the pending processed counter. */ 531b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 532b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_COUNT, 533b356ddf0SMark Johnston SAFEXCEL_xDR_PROC_CLR_COUNT); 534b356ddf0SMark Johnston 535b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 536b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_PNTR, 0); 537b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 538b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_PNTR, 0); 539b356ddf0SMark Johnston 540b356ddf0SMark Johnston /* Ring size. */ 541b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 542b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_RING_SIZE, 543b356ddf0SMark Johnston SAFEXCEL_RING_SIZE * sc->sc_config.rd_offset * 544b356ddf0SMark Johnston sizeof(uint32_t)); 545b356ddf0SMark Johnston } 546b356ddf0SMark Johnston } 547b356ddf0SMark Johnston 548b356ddf0SMark Johnston static void 549b356ddf0SMark Johnston safexcel_hw_setup_rings(struct safexcel_softc *sc) 550b356ddf0SMark Johnston { 551b356ddf0SMark Johnston struct safexcel_ring *ring; 552b356ddf0SMark Johnston uint32_t cd_size_rnd, mask, rd_size_rnd, val; 553b356ddf0SMark Johnston int i; 554b356ddf0SMark Johnston 555b356ddf0SMark Johnston mask = (1 << sc->sc_config.hdw) - 1; 556b356ddf0SMark Johnston cd_size_rnd = (sc->sc_config.cd_size + mask) >> sc->sc_config.hdw; 557b356ddf0SMark Johnston val = (sizeof(struct safexcel_res_descr) - 558b356ddf0SMark Johnston sizeof(struct safexcel_res_data)) / sizeof(uint32_t); 559b356ddf0SMark Johnston rd_size_rnd = (val + mask) >> sc->sc_config.hdw; 560b356ddf0SMark Johnston 561b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 562b356ddf0SMark Johnston ring = &sc->sc_ring[i]; 563b356ddf0SMark Johnston 564b356ddf0SMark Johnston /* 565b356ddf0SMark Johnston * Command descriptors. 566b356ddf0SMark Johnston */ 567b356ddf0SMark Johnston 568b356ddf0SMark Johnston /* Ring base address. */ 569b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_CDR(sc, i) + 570b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_LO, 571b356ddf0SMark Johnston SAFEXCEL_ADDR_LO(ring->cdr.dma.paddr)); 572b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_CDR(sc, i) + 573b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_HI, 574b356ddf0SMark Johnston SAFEXCEL_ADDR_HI(ring->cdr.dma.paddr)); 575b356ddf0SMark Johnston 576b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 577b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_DESC_SIZE, 578b356ddf0SMark Johnston SAFEXCEL_xDR_DESC_MODE_64BIT | SAFEXCEL_CDR_DESC_MODE_ADCP | 579b356ddf0SMark Johnston (sc->sc_config.cd_offset << SAFEXCEL_xDR_DESC_xD_OFFSET) | 580b356ddf0SMark Johnston sc->sc_config.cd_size); 581b356ddf0SMark Johnston 582b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 583b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_CFG, 584b356ddf0SMark Johnston ((SAFEXCEL_FETCH_COUNT * (cd_size_rnd << sc->sc_config.hdw)) << 585b356ddf0SMark Johnston SAFEXCEL_xDR_xD_FETCH_THRESH) | 586b356ddf0SMark Johnston (SAFEXCEL_FETCH_COUNT * sc->sc_config.cd_offset)); 587b356ddf0SMark Johnston 588b356ddf0SMark Johnston /* Configure DMA tx control. */ 589b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 590b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_DMA_CFG, 591b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_CFG_WR_CACHE(WR_CACHE_3BITS) | 592b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_CFG_RD_CACHE(RD_CACHE_3BITS)); 593b356ddf0SMark Johnston 594b356ddf0SMark Johnston /* Clear any pending interrupt. */ 595b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 596b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_STAT, 597b356ddf0SMark Johnston SAFEXCEL_CDR_INTR_MASK); 598b356ddf0SMark Johnston 599b356ddf0SMark Johnston /* 600b356ddf0SMark Johnston * Result descriptors. 601b356ddf0SMark Johnston */ 602b356ddf0SMark Johnston 603b356ddf0SMark Johnston /* Ring base address. */ 604b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_RDR(sc, i) + 605b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_LO, 606b356ddf0SMark Johnston SAFEXCEL_ADDR_LO(ring->rdr.dma.paddr)); 607b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_RDR(sc, i) + 608b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_HI, 609b356ddf0SMark Johnston SAFEXCEL_ADDR_HI(ring->rdr.dma.paddr)); 610b356ddf0SMark Johnston 611b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 612b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_DESC_SIZE, 613b356ddf0SMark Johnston SAFEXCEL_xDR_DESC_MODE_64BIT | 614b356ddf0SMark Johnston (sc->sc_config.rd_offset << SAFEXCEL_xDR_DESC_xD_OFFSET) | 615b356ddf0SMark Johnston sc->sc_config.rd_size); 616b356ddf0SMark Johnston 617b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 618b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_CFG, 619b356ddf0SMark Johnston ((SAFEXCEL_FETCH_COUNT * (rd_size_rnd << sc->sc_config.hdw)) << 620b356ddf0SMark Johnston SAFEXCEL_xDR_xD_FETCH_THRESH) | 621b356ddf0SMark Johnston (SAFEXCEL_FETCH_COUNT * sc->sc_config.rd_offset)); 622b356ddf0SMark Johnston 623b356ddf0SMark Johnston /* Configure DMA tx control. */ 624b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 625b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_DMA_CFG, 626b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_CFG_WR_CACHE(WR_CACHE_3BITS) | 627b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_CFG_RD_CACHE(RD_CACHE_3BITS) | 628b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_WR_RES_BUF | SAFEXCEL_HIA_xDR_WR_CTRL_BUF); 629b356ddf0SMark Johnston 630b356ddf0SMark Johnston /* Clear any pending interrupt. */ 631b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 632b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_STAT, 633b356ddf0SMark Johnston SAFEXCEL_RDR_INTR_MASK); 634b356ddf0SMark Johnston 635b356ddf0SMark Johnston /* Enable ring interrupt. */ 636b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 637b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R(sc) + SAFEXCEL_HIA_AIC_R_ENABLE_CTRL(i), 638b356ddf0SMark Johnston SAFEXCEL_RDR_IRQ(i)); 639b356ddf0SMark Johnston } 640b356ddf0SMark Johnston } 641b356ddf0SMark Johnston 642b356ddf0SMark Johnston /* Reset the command and result descriptor rings. */ 643b356ddf0SMark Johnston static void 644b356ddf0SMark Johnston safexcel_hw_reset_rings(struct safexcel_softc *sc) 645b356ddf0SMark Johnston { 646b356ddf0SMark Johnston int i; 647b356ddf0SMark Johnston 648b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 649b356ddf0SMark Johnston /* 650b356ddf0SMark Johnston * Result descriptor ring operations. 651b356ddf0SMark Johnston */ 652b356ddf0SMark Johnston 653b356ddf0SMark Johnston /* Reset ring base address. */ 654b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_RDR(sc, i) + 655b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_LO, 0); 656b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_RDR(sc, i) + 657b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_HI, 0); 658b356ddf0SMark Johnston 659b356ddf0SMark Johnston /* Clear the pending prepared counter. */ 660b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 661b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_COUNT, 662b356ddf0SMark Johnston SAFEXCEL_xDR_PREP_CLR_COUNT); 663b356ddf0SMark Johnston 664b356ddf0SMark Johnston /* Clear the pending processed counter. */ 665b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 666b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_COUNT, 667b356ddf0SMark Johnston SAFEXCEL_xDR_PROC_CLR_COUNT); 668b356ddf0SMark Johnston 669b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 670b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_PNTR, 0); 671b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 672b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_PNTR, 0); 673b356ddf0SMark Johnston 674b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 675b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_RING_SIZE, 0); 676b356ddf0SMark Johnston 677b356ddf0SMark Johnston /* Clear any pending interrupt. */ 678b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 679b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, i) + SAFEXCEL_HIA_xDR_STAT, 680b356ddf0SMark Johnston SAFEXCEL_RDR_INTR_MASK); 681b356ddf0SMark Johnston 682b356ddf0SMark Johnston /* Disable ring interrupt. */ 683b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 684b356ddf0SMark Johnston SAFEXCEL_HIA_AIC_R(sc) + SAFEXCEL_HIA_AIC_R_ENABLE_CLR(i), 685b356ddf0SMark Johnston SAFEXCEL_RDR_IRQ(i)); 686b356ddf0SMark Johnston 687b356ddf0SMark Johnston /* 688b356ddf0SMark Johnston * Command descriptor ring operations. 689b356ddf0SMark Johnston */ 690b356ddf0SMark Johnston 691b356ddf0SMark Johnston /* Reset ring base address. */ 692b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_CDR(sc, i) + 693b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_LO, 0); 694b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_CDR(sc, i) + 695b356ddf0SMark Johnston SAFEXCEL_HIA_xDR_RING_BASE_ADDR_HI, 0); 696b356ddf0SMark Johnston 697b356ddf0SMark Johnston /* Clear the pending prepared counter. */ 698b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 699b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_COUNT, 700b356ddf0SMark Johnston SAFEXCEL_xDR_PREP_CLR_COUNT); 701b356ddf0SMark Johnston 702b356ddf0SMark Johnston /* Clear the pending processed counter. */ 703b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 704b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_COUNT, 705b356ddf0SMark Johnston SAFEXCEL_xDR_PROC_CLR_COUNT); 706b356ddf0SMark Johnston 707b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 708b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PREP_PNTR, 0); 709b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 710b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_PROC_PNTR, 0); 711b356ddf0SMark Johnston 712b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 713b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_RING_SIZE, 0); 714b356ddf0SMark Johnston 715b356ddf0SMark Johnston /* Clear any pending interrupt. */ 716b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 717b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, i) + SAFEXCEL_HIA_xDR_STAT, 718b356ddf0SMark Johnston SAFEXCEL_CDR_INTR_MASK); 719b356ddf0SMark Johnston } 720b356ddf0SMark Johnston } 721b356ddf0SMark Johnston 722b356ddf0SMark Johnston static void 723b356ddf0SMark Johnston safexcel_enable_pe_engine(struct safexcel_softc *sc, int pe) 724b356ddf0SMark Johnston { 725b356ddf0SMark Johnston int i, ring_mask; 726b356ddf0SMark Johnston 727b356ddf0SMark Johnston for (ring_mask = 0, i = 0; i < sc->sc_config.rings; i++) { 728b356ddf0SMark Johnston ring_mask <<= 1; 729b356ddf0SMark Johnston ring_mask |= 1; 730b356ddf0SMark Johnston } 731b356ddf0SMark Johnston 732b356ddf0SMark Johnston /* Enable command descriptor rings. */ 733b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_DFE_THR(sc) + SAFEXCEL_HIA_DFE_THR_CTRL(pe), 734b356ddf0SMark Johnston SAFEXCEL_DxE_THR_CTRL_EN | ring_mask); 735b356ddf0SMark Johnston 736b356ddf0SMark Johnston /* Enable result descriptor rings. */ 737b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_DSE_THR(sc) + SAFEXCEL_HIA_DSE_THR_CTRL(pe), 738b356ddf0SMark Johnston SAFEXCEL_DxE_THR_CTRL_EN | ring_mask); 739b356ddf0SMark Johnston 740b356ddf0SMark Johnston /* Clear any HIA interrupt. */ 741b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, SAFEXCEL_HIA_AIC_G(sc) + SAFEXCEL_HIA_AIC_G_ACK, 742b356ddf0SMark Johnston SAFEXCEL_AIC_G_ACK_HIA_MASK); 743b356ddf0SMark Johnston } 744b356ddf0SMark Johnston 745b356ddf0SMark Johnston static void 746b356ddf0SMark Johnston safexcel_execute(struct safexcel_softc *sc, struct safexcel_ring *ring, 747b356ddf0SMark Johnston struct safexcel_request *req) 748b356ddf0SMark Johnston { 749b356ddf0SMark Johnston uint32_t ncdescs, nrdescs, nreqs; 750b356ddf0SMark Johnston int ringidx; 751b356ddf0SMark Johnston bool busy; 752b356ddf0SMark Johnston 753b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 754b356ddf0SMark Johnston 755e934d455SMark Johnston ringidx = req->ringidx; 756b356ddf0SMark Johnston busy = !STAILQ_EMPTY(&ring->queued_requests); 757b356ddf0SMark Johnston ncdescs = nrdescs = nreqs = 0; 758b356ddf0SMark Johnston while ((req = STAILQ_FIRST(&ring->ready_requests)) != NULL && 759b356ddf0SMark Johnston req->cdescs + ncdescs <= SAFEXCEL_MAX_BATCH_SIZE && 760b356ddf0SMark Johnston req->rdescs + nrdescs <= SAFEXCEL_MAX_BATCH_SIZE) { 761b356ddf0SMark Johnston STAILQ_REMOVE_HEAD(&ring->ready_requests, link); 762b356ddf0SMark Johnston STAILQ_INSERT_TAIL(&ring->queued_requests, req, link); 763b356ddf0SMark Johnston ncdescs += req->cdescs; 764b356ddf0SMark Johnston nrdescs += req->rdescs; 765b356ddf0SMark Johnston nreqs++; 766b356ddf0SMark Johnston } 767b356ddf0SMark Johnston 768b356ddf0SMark Johnston if (!busy) { 769b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 770b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ringidx) + SAFEXCEL_HIA_xDR_THRESH, 771b356ddf0SMark Johnston SAFEXCEL_HIA_CDR_THRESH_PKT_MODE | nreqs); 772b356ddf0SMark Johnston } 773b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 774b356ddf0SMark Johnston SAFEXCEL_HIA_RDR(sc, ringidx) + SAFEXCEL_HIA_xDR_PREP_COUNT, 775b356ddf0SMark Johnston nrdescs * sc->sc_config.rd_offset * sizeof(uint32_t)); 776b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 777b356ddf0SMark Johnston SAFEXCEL_HIA_CDR(sc, ringidx) + SAFEXCEL_HIA_xDR_PREP_COUNT, 778b356ddf0SMark Johnston ncdescs * sc->sc_config.cd_offset * sizeof(uint32_t)); 779b356ddf0SMark Johnston } 780b356ddf0SMark Johnston 781b356ddf0SMark Johnston static void 782b356ddf0SMark Johnston safexcel_init_rings(struct safexcel_softc *sc) 783b356ddf0SMark Johnston { 784b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 785b356ddf0SMark Johnston struct safexcel_ring *ring; 786b356ddf0SMark Johnston uint64_t atok; 787b356ddf0SMark Johnston int i, j; 788b356ddf0SMark Johnston 789b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 790b356ddf0SMark Johnston ring = &sc->sc_ring[i]; 791b356ddf0SMark Johnston 7928ba6acbbSMark Johnston snprintf(ring->lockname, sizeof(ring->lockname), 7938ba6acbbSMark Johnston "safexcel_ring%d", i); 7948ba6acbbSMark Johnston mtx_init(&ring->mtx, ring->lockname, NULL, MTX_DEF); 795b356ddf0SMark Johnston STAILQ_INIT(&ring->free_requests); 796b356ddf0SMark Johnston STAILQ_INIT(&ring->ready_requests); 797b356ddf0SMark Johnston STAILQ_INIT(&ring->queued_requests); 798b356ddf0SMark Johnston 799b356ddf0SMark Johnston ring->cdr.read = ring->cdr.write = 0; 800b356ddf0SMark Johnston ring->rdr.read = ring->rdr.write = 0; 801b356ddf0SMark Johnston for (j = 0; j < SAFEXCEL_RING_SIZE; j++) { 802b356ddf0SMark Johnston cdesc = &ring->cdr.desc[j]; 803b356ddf0SMark Johnston atok = ring->dma_atok.paddr + 804b356ddf0SMark Johnston sc->sc_config.atok_offset * j; 805b356ddf0SMark Johnston cdesc->atok_lo = SAFEXCEL_ADDR_LO(atok); 806b356ddf0SMark Johnston cdesc->atok_hi = SAFEXCEL_ADDR_HI(atok); 807b356ddf0SMark Johnston } 808b356ddf0SMark Johnston } 809b356ddf0SMark Johnston } 810b356ddf0SMark Johnston 811b356ddf0SMark Johnston static void 812b356ddf0SMark Johnston safexcel_dma_alloc_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, 813b356ddf0SMark Johnston int error) 814b356ddf0SMark Johnston { 815b356ddf0SMark Johnston struct safexcel_dma_mem *sdm; 816b356ddf0SMark Johnston 817b356ddf0SMark Johnston if (error != 0) 818b356ddf0SMark Johnston return; 819b356ddf0SMark Johnston 820b356ddf0SMark Johnston KASSERT(nseg == 1, ("%s: nsegs is %d", __func__, nseg)); 821b356ddf0SMark Johnston sdm = arg; 822b356ddf0SMark Johnston sdm->paddr = segs->ds_addr; 823b356ddf0SMark Johnston } 824b356ddf0SMark Johnston 825b356ddf0SMark Johnston static int 826b356ddf0SMark Johnston safexcel_dma_alloc_mem(struct safexcel_softc *sc, struct safexcel_dma_mem *sdm, 827b356ddf0SMark Johnston bus_size_t size) 828b356ddf0SMark Johnston { 829b356ddf0SMark Johnston int error; 830b356ddf0SMark Johnston 831b356ddf0SMark Johnston KASSERT(sdm->vaddr == NULL, 832b356ddf0SMark Johnston ("%s: DMA memory descriptor in use.", __func__)); 833b356ddf0SMark Johnston 834b356ddf0SMark Johnston error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */ 835b356ddf0SMark Johnston PAGE_SIZE, 0, /* alignment, boundary */ 836b356ddf0SMark Johnston BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 837b356ddf0SMark Johnston BUS_SPACE_MAXADDR, /* highaddr */ 838b356ddf0SMark Johnston NULL, NULL, /* filtfunc, filtfuncarg */ 839b356ddf0SMark Johnston size, 1, /* maxsize, nsegments */ 840b356ddf0SMark Johnston size, BUS_DMA_COHERENT, /* maxsegsz, flags */ 841b356ddf0SMark Johnston NULL, NULL, /* lockfunc, lockfuncarg */ 842b356ddf0SMark Johnston &sdm->tag); /* dmat */ 843b356ddf0SMark Johnston if (error != 0) { 844b356ddf0SMark Johnston device_printf(sc->sc_dev, 845b356ddf0SMark Johnston "failed to allocate busdma tag, error %d\n", error); 846b356ddf0SMark Johnston goto err1; 847b356ddf0SMark Johnston } 848b356ddf0SMark Johnston 849b356ddf0SMark Johnston error = bus_dmamem_alloc(sdm->tag, (void **)&sdm->vaddr, 850b356ddf0SMark Johnston BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT, &sdm->map); 851b356ddf0SMark Johnston if (error != 0) { 852b356ddf0SMark Johnston device_printf(sc->sc_dev, 853b356ddf0SMark Johnston "failed to allocate DMA safe memory, error %d\n", error); 854b356ddf0SMark Johnston goto err2; 855b356ddf0SMark Johnston } 856b356ddf0SMark Johnston 857b356ddf0SMark Johnston error = bus_dmamap_load(sdm->tag, sdm->map, sdm->vaddr, size, 858b356ddf0SMark Johnston safexcel_dma_alloc_mem_cb, sdm, BUS_DMA_NOWAIT); 859b356ddf0SMark Johnston if (error != 0) { 860b356ddf0SMark Johnston device_printf(sc->sc_dev, 861b356ddf0SMark Johnston "cannot get address of the DMA memory, error %d\n", error); 862b356ddf0SMark Johnston goto err3; 863b356ddf0SMark Johnston } 864b356ddf0SMark Johnston 865b356ddf0SMark Johnston return (0); 866b356ddf0SMark Johnston err3: 867b356ddf0SMark Johnston bus_dmamem_free(sdm->tag, sdm->vaddr, sdm->map); 868b356ddf0SMark Johnston err2: 869b356ddf0SMark Johnston bus_dma_tag_destroy(sdm->tag); 870b356ddf0SMark Johnston err1: 871b356ddf0SMark Johnston sdm->vaddr = NULL; 872b356ddf0SMark Johnston 873b356ddf0SMark Johnston return (error); 874b356ddf0SMark Johnston } 875b356ddf0SMark Johnston 876b356ddf0SMark Johnston static void 877b356ddf0SMark Johnston safexcel_dma_free_mem(struct safexcel_dma_mem *sdm) 878b356ddf0SMark Johnston { 879b356ddf0SMark Johnston bus_dmamap_unload(sdm->tag, sdm->map); 880b356ddf0SMark Johnston bus_dmamem_free(sdm->tag, sdm->vaddr, sdm->map); 881b356ddf0SMark Johnston bus_dma_tag_destroy(sdm->tag); 882b356ddf0SMark Johnston } 883b356ddf0SMark Johnston 884b356ddf0SMark Johnston static void 885b356ddf0SMark Johnston safexcel_dma_free_rings(struct safexcel_softc *sc) 886b356ddf0SMark Johnston { 887b356ddf0SMark Johnston struct safexcel_ring *ring; 888b356ddf0SMark Johnston int i; 889b356ddf0SMark Johnston 890b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 891b356ddf0SMark Johnston ring = &sc->sc_ring[i]; 892b356ddf0SMark Johnston safexcel_dma_free_mem(&ring->cdr.dma); 893b356ddf0SMark Johnston safexcel_dma_free_mem(&ring->dma_atok); 894b356ddf0SMark Johnston safexcel_dma_free_mem(&ring->rdr.dma); 895b356ddf0SMark Johnston bus_dma_tag_destroy(ring->data_dtag); 896b356ddf0SMark Johnston mtx_destroy(&ring->mtx); 897b356ddf0SMark Johnston } 898b356ddf0SMark Johnston } 899b356ddf0SMark Johnston 900b356ddf0SMark Johnston static int 901b356ddf0SMark Johnston safexcel_dma_init(struct safexcel_softc *sc) 902b356ddf0SMark Johnston { 903b356ddf0SMark Johnston struct safexcel_ring *ring; 90439523b48SMark Johnston bus_size_t size; 90539523b48SMark Johnston int error, i; 906b356ddf0SMark Johnston 907b356ddf0SMark Johnston for (i = 0; i < sc->sc_config.rings; i++) { 908b356ddf0SMark Johnston ring = &sc->sc_ring[i]; 909b356ddf0SMark Johnston 910b356ddf0SMark Johnston error = bus_dma_tag_create( 911b356ddf0SMark Johnston bus_get_dma_tag(sc->sc_dev),/* parent */ 912b356ddf0SMark Johnston 1, 0, /* alignment, boundary */ 913b356ddf0SMark Johnston BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 914b356ddf0SMark Johnston BUS_SPACE_MAXADDR, /* highaddr */ 915b356ddf0SMark Johnston NULL, NULL, /* filtfunc, filtfuncarg */ 916b356ddf0SMark Johnston SAFEXCEL_MAX_REQUEST_SIZE, /* maxsize */ 917b356ddf0SMark Johnston SAFEXCEL_MAX_FRAGMENTS, /* nsegments */ 918b356ddf0SMark Johnston SAFEXCEL_MAX_REQUEST_SIZE, /* maxsegsz */ 919b356ddf0SMark Johnston BUS_DMA_COHERENT, /* flags */ 920b356ddf0SMark Johnston NULL, NULL, /* lockfunc, lockfuncarg */ 921b356ddf0SMark Johnston &ring->data_dtag); /* dmat */ 922b356ddf0SMark Johnston if (error != 0) { 923b356ddf0SMark Johnston device_printf(sc->sc_dev, 924b356ddf0SMark Johnston "bus_dma_tag_create main failed; error %d\n", error); 925b356ddf0SMark Johnston return (error); 926b356ddf0SMark Johnston } 927b356ddf0SMark Johnston 928b356ddf0SMark Johnston size = sizeof(uint32_t) * sc->sc_config.cd_offset * 929b356ddf0SMark Johnston SAFEXCEL_RING_SIZE; 930b356ddf0SMark Johnston error = safexcel_dma_alloc_mem(sc, &ring->cdr.dma, size); 931b356ddf0SMark Johnston if (error != 0) { 932b356ddf0SMark Johnston device_printf(sc->sc_dev, 933b356ddf0SMark Johnston "failed to allocate CDR DMA memory, error %d\n", 934b356ddf0SMark Johnston error); 935b356ddf0SMark Johnston goto err; 936b356ddf0SMark Johnston } 937b356ddf0SMark Johnston ring->cdr.desc = 938b356ddf0SMark Johnston (struct safexcel_cmd_descr *)ring->cdr.dma.vaddr; 939b356ddf0SMark Johnston 940b356ddf0SMark Johnston /* Allocate additional CDR token memory. */ 94139523b48SMark Johnston size = (bus_size_t)sc->sc_config.atok_offset * 94239523b48SMark Johnston SAFEXCEL_RING_SIZE; 94339523b48SMark Johnston error = safexcel_dma_alloc_mem(sc, &ring->dma_atok, size); 944b356ddf0SMark Johnston if (error != 0) { 945b356ddf0SMark Johnston device_printf(sc->sc_dev, 946b356ddf0SMark Johnston "failed to allocate atoken DMA memory, error %d\n", 947b356ddf0SMark Johnston error); 948b356ddf0SMark Johnston goto err; 949b356ddf0SMark Johnston } 950b356ddf0SMark Johnston 951b356ddf0SMark Johnston size = sizeof(uint32_t) * sc->sc_config.rd_offset * 952b356ddf0SMark Johnston SAFEXCEL_RING_SIZE; 953b356ddf0SMark Johnston error = safexcel_dma_alloc_mem(sc, &ring->rdr.dma, size); 954b356ddf0SMark Johnston if (error) { 955b356ddf0SMark Johnston device_printf(sc->sc_dev, 956b356ddf0SMark Johnston "failed to allocate RDR DMA memory, error %d\n", 957b356ddf0SMark Johnston error); 958b356ddf0SMark Johnston goto err; 959b356ddf0SMark Johnston } 960b356ddf0SMark Johnston ring->rdr.desc = 961b356ddf0SMark Johnston (struct safexcel_res_descr *)ring->rdr.dma.vaddr; 962b356ddf0SMark Johnston } 963b356ddf0SMark Johnston 964b356ddf0SMark Johnston return (0); 965b356ddf0SMark Johnston err: 966b356ddf0SMark Johnston safexcel_dma_free_rings(sc); 967b356ddf0SMark Johnston return (error); 968b356ddf0SMark Johnston } 969b356ddf0SMark Johnston 970b356ddf0SMark Johnston static void 971b356ddf0SMark Johnston safexcel_deinit_hw(struct safexcel_softc *sc) 972b356ddf0SMark Johnston { 973b356ddf0SMark Johnston safexcel_hw_reset_rings(sc); 974b356ddf0SMark Johnston safexcel_dma_free_rings(sc); 975b356ddf0SMark Johnston } 976b356ddf0SMark Johnston 977b356ddf0SMark Johnston static int 978b356ddf0SMark Johnston safexcel_init_hw(struct safexcel_softc *sc) 979b356ddf0SMark Johnston { 980b356ddf0SMark Johnston int pe; 981b356ddf0SMark Johnston 982b356ddf0SMark Johnston /* 23.3.7 Initialization */ 983b356ddf0SMark Johnston if (safexcel_configure(sc) != 0) 984b356ddf0SMark Johnston return (EINVAL); 985b356ddf0SMark Johnston 986b356ddf0SMark Johnston if (safexcel_dma_init(sc) != 0) 987b356ddf0SMark Johnston return (ENOMEM); 988b356ddf0SMark Johnston 989b356ddf0SMark Johnston safexcel_init_rings(sc); 990b356ddf0SMark Johnston 991b356ddf0SMark Johnston safexcel_init_hia_bus_access(sc); 992b356ddf0SMark Johnston 993b356ddf0SMark Johnston /* 23.3.7.2 Disable EIP-97 global Interrupts */ 994b356ddf0SMark Johnston safexcel_disable_global_interrupts(sc); 995b356ddf0SMark Johnston 996b356ddf0SMark Johnston for (pe = 0; pe < sc->sc_config.pes; pe++) { 997b356ddf0SMark Johnston /* 23.3.7.3 Configure Data Fetch Engine */ 998b356ddf0SMark Johnston safexcel_configure_dfe_engine(sc, pe); 999b356ddf0SMark Johnston 1000b356ddf0SMark Johnston /* 23.3.7.4 Configure Data Store Engine */ 1001b356ddf0SMark Johnston if (safexcel_configure_dse(sc, pe)) { 1002b356ddf0SMark Johnston safexcel_deinit_hw(sc); 1003b356ddf0SMark Johnston return (-1); 1004b356ddf0SMark Johnston } 1005b356ddf0SMark Johnston 1006b356ddf0SMark Johnston /* 23.3.7.5 1. Protocol enables */ 1007b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 1008b356ddf0SMark Johnston SAFEXCEL_PE(sc) + SAFEXCEL_PE_EIP96_FUNCTION_EN(pe), 1009b356ddf0SMark Johnston 0xffffffff); 1010b356ddf0SMark Johnston SAFEXCEL_WRITE(sc, 1011b356ddf0SMark Johnston SAFEXCEL_PE(sc) + SAFEXCEL_PE_EIP96_FUNCTION2_EN(pe), 1012b356ddf0SMark Johnston 0xffffffff); 1013b356ddf0SMark Johnston } 1014b356ddf0SMark Johnston 1015b356ddf0SMark Johnston safexcel_hw_prepare_rings(sc); 1016b356ddf0SMark Johnston 1017b356ddf0SMark Johnston /* 23.3.7.5 Configure the Processing Engine(s). */ 1018b356ddf0SMark Johnston for (pe = 0; pe < sc->sc_config.pes; pe++) 1019b356ddf0SMark Johnston safexcel_enable_pe_engine(sc, pe); 1020b356ddf0SMark Johnston 1021b356ddf0SMark Johnston safexcel_hw_setup_rings(sc); 1022b356ddf0SMark Johnston 1023b356ddf0SMark Johnston return (0); 1024b356ddf0SMark Johnston } 1025b356ddf0SMark Johnston 1026b356ddf0SMark Johnston static int 1027b356ddf0SMark Johnston safexcel_setup_dev_interrupts(struct safexcel_softc *sc) 1028b356ddf0SMark Johnston { 1029e934d455SMark Johnston int error, i, j; 1030b356ddf0SMark Johnston 1031b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RINGS && sc->sc_intr[i] != NULL; i++) { 1032b356ddf0SMark Johnston sc->sc_ih[i].sc = sc; 1033b356ddf0SMark Johnston sc->sc_ih[i].ring = i; 1034b356ddf0SMark Johnston 1035b356ddf0SMark Johnston if (bus_setup_intr(sc->sc_dev, sc->sc_intr[i], 1036b356ddf0SMark Johnston INTR_TYPE_NET | INTR_MPSAFE, NULL, safexcel_ring_intr, 1037b356ddf0SMark Johnston &sc->sc_ih[i], &sc->sc_ih[i].handle)) { 1038b356ddf0SMark Johnston device_printf(sc->sc_dev, 1039b356ddf0SMark Johnston "couldn't setup interrupt %d\n", i); 1040b356ddf0SMark Johnston goto err; 1041b356ddf0SMark Johnston } 1042e934d455SMark Johnston 1043e934d455SMark Johnston error = bus_bind_intr(sc->sc_dev, sc->sc_intr[i], i % mp_ncpus); 1044e934d455SMark Johnston if (error != 0) 1045e934d455SMark Johnston device_printf(sc->sc_dev, 1046e934d455SMark Johnston "failed to bind ring %d\n", error); 1047b356ddf0SMark Johnston } 1048b356ddf0SMark Johnston 1049b356ddf0SMark Johnston return (0); 1050b356ddf0SMark Johnston 1051b356ddf0SMark Johnston err: 1052b356ddf0SMark Johnston for (j = 0; j < i; j++) 1053b356ddf0SMark Johnston bus_teardown_intr(sc->sc_dev, sc->sc_intr[j], 1054b356ddf0SMark Johnston sc->sc_ih[j].handle); 1055b356ddf0SMark Johnston 1056b356ddf0SMark Johnston return (ENXIO); 1057b356ddf0SMark Johnston } 1058b356ddf0SMark Johnston 1059b356ddf0SMark Johnston static void 1060b356ddf0SMark Johnston safexcel_teardown_dev_interrupts(struct safexcel_softc *sc) 1061b356ddf0SMark Johnston { 1062b356ddf0SMark Johnston int i; 1063b356ddf0SMark Johnston 1064b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RINGS; i++) 1065b356ddf0SMark Johnston bus_teardown_intr(sc->sc_dev, sc->sc_intr[i], 1066b356ddf0SMark Johnston sc->sc_ih[i].handle); 1067b356ddf0SMark Johnston } 1068b356ddf0SMark Johnston 1069b356ddf0SMark Johnston static int 1070b356ddf0SMark Johnston safexcel_alloc_dev_resources(struct safexcel_softc *sc) 1071b356ddf0SMark Johnston { 1072b356ddf0SMark Johnston char name[16]; 1073b356ddf0SMark Johnston device_t dev; 1074b356ddf0SMark Johnston phandle_t node; 1075b356ddf0SMark Johnston int error, i, rid; 1076b356ddf0SMark Johnston 1077b356ddf0SMark Johnston dev = sc->sc_dev; 1078b356ddf0SMark Johnston node = ofw_bus_get_node(dev); 1079b356ddf0SMark Johnston 1080b356ddf0SMark Johnston rid = 0; 1081b356ddf0SMark Johnston sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 1082b356ddf0SMark Johnston RF_ACTIVE); 1083b356ddf0SMark Johnston if (sc->sc_res == NULL) { 1084b356ddf0SMark Johnston device_printf(dev, "couldn't allocate memory resources\n"); 1085b356ddf0SMark Johnston return (ENXIO); 1086b356ddf0SMark Johnston } 1087b356ddf0SMark Johnston 1088b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RINGS; i++) { 1089b356ddf0SMark Johnston (void)snprintf(name, sizeof(name), "ring%d", i); 1090b356ddf0SMark Johnston error = ofw_bus_find_string_index(node, "interrupt-names", name, 1091b356ddf0SMark Johnston &rid); 1092b356ddf0SMark Johnston if (error != 0) 1093b356ddf0SMark Johnston break; 1094b356ddf0SMark Johnston 1095b356ddf0SMark Johnston sc->sc_intr[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1096b356ddf0SMark Johnston RF_ACTIVE | RF_SHAREABLE); 1097b356ddf0SMark Johnston if (sc->sc_intr[i] == NULL) { 1098b356ddf0SMark Johnston error = ENXIO; 1099b356ddf0SMark Johnston goto out; 1100b356ddf0SMark Johnston } 1101b356ddf0SMark Johnston } 1102b356ddf0SMark Johnston if (i == 0) { 1103b356ddf0SMark Johnston device_printf(dev, "couldn't allocate interrupt resources\n"); 1104b356ddf0SMark Johnston error = ENXIO; 1105b356ddf0SMark Johnston goto out; 1106b356ddf0SMark Johnston } 1107b356ddf0SMark Johnston 1108b356ddf0SMark Johnston return (0); 1109b356ddf0SMark Johnston 1110b356ddf0SMark Johnston out: 1111b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RINGS && sc->sc_intr[i] != NULL; i++) 1112b356ddf0SMark Johnston bus_release_resource(dev, SYS_RES_IRQ, 1113b356ddf0SMark Johnston rman_get_rid(sc->sc_intr[i]), sc->sc_intr[i]); 1114b356ddf0SMark Johnston bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->sc_res), 1115b356ddf0SMark Johnston sc->sc_res); 1116b356ddf0SMark Johnston return (error); 1117b356ddf0SMark Johnston } 1118b356ddf0SMark Johnston 1119b356ddf0SMark Johnston static void 1120b356ddf0SMark Johnston safexcel_free_dev_resources(struct safexcel_softc *sc) 1121b356ddf0SMark Johnston { 1122b356ddf0SMark Johnston int i; 1123b356ddf0SMark Johnston 1124b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_MAX_RINGS && sc->sc_intr[i] != NULL; i++) 1125b356ddf0SMark Johnston bus_release_resource(sc->sc_dev, SYS_RES_IRQ, 1126b356ddf0SMark Johnston rman_get_rid(sc->sc_intr[i]), sc->sc_intr[i]); 1127b356ddf0SMark Johnston if (sc->sc_res != NULL) 1128b356ddf0SMark Johnston bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, 1129b356ddf0SMark Johnston rman_get_rid(sc->sc_res), sc->sc_res); 1130b356ddf0SMark Johnston } 1131b356ddf0SMark Johnston 1132b356ddf0SMark Johnston static int 1133b356ddf0SMark Johnston safexcel_probe(device_t dev) 1134b356ddf0SMark Johnston { 1135b356ddf0SMark Johnston struct safexcel_softc *sc; 1136b356ddf0SMark Johnston 1137b356ddf0SMark Johnston if (!ofw_bus_status_okay(dev)) 1138b356ddf0SMark Johnston return (ENXIO); 1139b356ddf0SMark Johnston 1140b356ddf0SMark Johnston sc = device_get_softc(dev); 1141b356ddf0SMark Johnston sc->sc_type = ofw_bus_search_compatible(dev, safexcel_compat)->ocd_data; 1142b356ddf0SMark Johnston if (sc->sc_type == 0) 1143b356ddf0SMark Johnston return (ENXIO); 1144b356ddf0SMark Johnston 1145b356ddf0SMark Johnston device_set_desc(dev, "SafeXcel EIP-97 crypto accelerator"); 1146b356ddf0SMark Johnston 1147b356ddf0SMark Johnston return (BUS_PROBE_DEFAULT); 1148b356ddf0SMark Johnston } 1149b356ddf0SMark Johnston 1150b356ddf0SMark Johnston static int 1151b356ddf0SMark Johnston safexcel_attach(device_t dev) 1152b356ddf0SMark Johnston { 1153*0371c3faSMark Johnston struct sysctl_ctx_list *ctx; 1154*0371c3faSMark Johnston struct sysctl_oid *oid; 1155*0371c3faSMark Johnston struct sysctl_oid_list *children; 1156b356ddf0SMark Johnston struct safexcel_softc *sc; 1157b356ddf0SMark Johnston struct safexcel_request *req; 1158b356ddf0SMark Johnston struct safexcel_ring *ring; 1159b356ddf0SMark Johnston int i, j, ringidx; 1160b356ddf0SMark Johnston 1161b356ddf0SMark Johnston sc = device_get_softc(dev); 1162b356ddf0SMark Johnston sc->sc_dev = dev; 1163b356ddf0SMark Johnston sc->sc_cid = -1; 1164b356ddf0SMark Johnston 1165b356ddf0SMark Johnston if (safexcel_alloc_dev_resources(sc)) 1166b356ddf0SMark Johnston goto err; 1167b356ddf0SMark Johnston 1168b356ddf0SMark Johnston if (safexcel_setup_dev_interrupts(sc)) 1169b356ddf0SMark Johnston goto err1; 1170b356ddf0SMark Johnston 1171b356ddf0SMark Johnston if (safexcel_init_hw(sc)) 1172b356ddf0SMark Johnston goto err2; 1173b356ddf0SMark Johnston 1174b356ddf0SMark Johnston for (ringidx = 0; ringidx < sc->sc_config.rings; ringidx++) { 1175b356ddf0SMark Johnston ring = &sc->sc_ring[ringidx]; 1176b356ddf0SMark Johnston 1177b356ddf0SMark Johnston ring->cmd_data = sglist_alloc(SAFEXCEL_MAX_FRAGMENTS, M_WAITOK); 1178b356ddf0SMark Johnston ring->res_data = sglist_alloc(SAFEXCEL_MAX_FRAGMENTS, M_WAITOK); 1179b356ddf0SMark Johnston 1180b356ddf0SMark Johnston ring->requests = mallocarray(SAFEXCEL_REQUESTS_PER_RING, 1181b356ddf0SMark Johnston sizeof(struct safexcel_request), M_SAFEXCEL, 1182b356ddf0SMark Johnston M_WAITOK | M_ZERO); 1183b356ddf0SMark Johnston 1184b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_REQUESTS_PER_RING; i++) { 1185b356ddf0SMark Johnston req = &ring->requests[i]; 1186b356ddf0SMark Johnston req->sc = sc; 1187e934d455SMark Johnston req->ringidx = ringidx; 1188b356ddf0SMark Johnston if (bus_dmamap_create(ring->data_dtag, 1189b356ddf0SMark Johnston BUS_DMA_COHERENT, &req->dmap) != 0) { 1190b356ddf0SMark Johnston for (j = 0; j < i; j++) 1191b356ddf0SMark Johnston bus_dmamap_destroy(ring->data_dtag, 1192b356ddf0SMark Johnston ring->requests[j].dmap); 1193b356ddf0SMark Johnston goto err2; 1194b356ddf0SMark Johnston } 1195b356ddf0SMark Johnston if (safexcel_dma_alloc_mem(sc, &req->ctx, 1196b356ddf0SMark Johnston sizeof(struct safexcel_context_record)) != 0) { 1197b356ddf0SMark Johnston for (j = 0; j < i; j++) { 1198b356ddf0SMark Johnston bus_dmamap_destroy(ring->data_dtag, 1199b356ddf0SMark Johnston ring->requests[j].dmap); 1200b356ddf0SMark Johnston safexcel_dma_free_mem( 1201b356ddf0SMark Johnston &ring->requests[j].ctx); 1202b356ddf0SMark Johnston } 1203b356ddf0SMark Johnston goto err2; 1204b356ddf0SMark Johnston } 1205b356ddf0SMark Johnston STAILQ_INSERT_TAIL(&ring->free_requests, req, link); 1206b356ddf0SMark Johnston } 1207b356ddf0SMark Johnston } 1208b356ddf0SMark Johnston 1209*0371c3faSMark Johnston ctx = device_get_sysctl_ctx(dev); 1210*0371c3faSMark Johnston SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1211b356ddf0SMark Johnston OID_AUTO, "debug", CTLFLAG_RWTUN, &sc->sc_debug, 0, 1212b356ddf0SMark Johnston "Debug message verbosity"); 1213b356ddf0SMark Johnston 1214*0371c3faSMark Johnston oid = device_get_sysctl_tree(sc->sc_dev); 1215*0371c3faSMark Johnston children = SYSCTL_CHILDREN(oid); 1216*0371c3faSMark Johnston oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", 1217*0371c3faSMark Johnston CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "statistics"); 1218*0371c3faSMark Johnston children = SYSCTL_CHILDREN(oid); 1219*0371c3faSMark Johnston 1220*0371c3faSMark Johnston sc->sc_req_alloc_failures = counter_u64_alloc(M_WAITOK); 1221*0371c3faSMark Johnston SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "req_alloc_failures", 1222*0371c3faSMark Johnston CTLFLAG_RD, &sc->sc_req_alloc_failures, 1223*0371c3faSMark Johnston "Number of request allocation failures"); 1224*0371c3faSMark Johnston sc->sc_cdesc_alloc_failures = counter_u64_alloc(M_WAITOK); 1225*0371c3faSMark Johnston SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "cdesc_alloc_failures", 1226*0371c3faSMark Johnston CTLFLAG_RD, &sc->sc_cdesc_alloc_failures, 1227*0371c3faSMark Johnston "Number of command descriptor ring overflows"); 1228*0371c3faSMark Johnston sc->sc_rdesc_alloc_failures = counter_u64_alloc(M_WAITOK); 1229*0371c3faSMark Johnston SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "rdesc_alloc_failures", 1230*0371c3faSMark Johnston CTLFLAG_RD, &sc->sc_rdesc_alloc_failures, 1231*0371c3faSMark Johnston "Number of result descriptor ring overflows"); 1232*0371c3faSMark Johnston 1233b356ddf0SMark Johnston sc->sc_cid = crypto_get_driverid(dev, sizeof(struct safexcel_session), 1234b356ddf0SMark Johnston CRYPTOCAP_F_HARDWARE); 1235b356ddf0SMark Johnston if (sc->sc_cid < 0) 1236b356ddf0SMark Johnston goto err2; 1237b356ddf0SMark Johnston 1238b356ddf0SMark Johnston return (0); 1239b356ddf0SMark Johnston 1240b356ddf0SMark Johnston err2: 1241b356ddf0SMark Johnston safexcel_teardown_dev_interrupts(sc); 1242b356ddf0SMark Johnston err1: 1243b356ddf0SMark Johnston safexcel_free_dev_resources(sc); 1244b356ddf0SMark Johnston err: 1245b356ddf0SMark Johnston return (ENXIO); 1246b356ddf0SMark Johnston } 1247b356ddf0SMark Johnston 1248b356ddf0SMark Johnston static int 1249b356ddf0SMark Johnston safexcel_detach(device_t dev) 1250b356ddf0SMark Johnston { 1251b356ddf0SMark Johnston struct safexcel_ring *ring; 1252b356ddf0SMark Johnston struct safexcel_softc *sc; 1253b356ddf0SMark Johnston int i, ringidx; 1254b356ddf0SMark Johnston 1255b356ddf0SMark Johnston sc = device_get_softc(dev); 1256b356ddf0SMark Johnston 1257b356ddf0SMark Johnston if (sc->sc_cid >= 0) 1258b356ddf0SMark Johnston crypto_unregister_all(sc->sc_cid); 1259*0371c3faSMark Johnston 1260*0371c3faSMark Johnston counter_u64_free(sc->sc_req_alloc_failures); 1261*0371c3faSMark Johnston counter_u64_free(sc->sc_cdesc_alloc_failures); 1262*0371c3faSMark Johnston counter_u64_free(sc->sc_rdesc_alloc_failures); 1263*0371c3faSMark Johnston 1264b356ddf0SMark Johnston for (ringidx = 0; ringidx < sc->sc_config.rings; ringidx++) { 1265b356ddf0SMark Johnston ring = &sc->sc_ring[ringidx]; 1266b356ddf0SMark Johnston for (i = 0; i < SAFEXCEL_REQUESTS_PER_RING; i++) { 1267b356ddf0SMark Johnston bus_dmamap_destroy(ring->data_dtag, 1268b356ddf0SMark Johnston ring->requests[i].dmap); 1269b356ddf0SMark Johnston safexcel_dma_free_mem(&ring->requests[i].ctx); 1270b356ddf0SMark Johnston } 1271b356ddf0SMark Johnston free(ring->requests, M_SAFEXCEL); 1272b356ddf0SMark Johnston sglist_free(ring->cmd_data); 1273b356ddf0SMark Johnston sglist_free(ring->res_data); 1274b356ddf0SMark Johnston } 1275b356ddf0SMark Johnston safexcel_deinit_hw(sc); 1276b356ddf0SMark Johnston safexcel_teardown_dev_interrupts(sc); 1277b356ddf0SMark Johnston safexcel_free_dev_resources(sc); 1278b356ddf0SMark Johnston 1279b356ddf0SMark Johnston return (0); 1280b356ddf0SMark Johnston } 1281b356ddf0SMark Johnston 1282b356ddf0SMark Johnston /* 1283b356ddf0SMark Johnston * Populate the request's context record with pre-computed key material. 1284b356ddf0SMark Johnston */ 1285b356ddf0SMark Johnston static int 1286b356ddf0SMark Johnston safexcel_set_context(struct safexcel_request *req) 1287b356ddf0SMark Johnston { 1288b356ddf0SMark Johnston const struct crypto_session_params *csp; 1289b356ddf0SMark Johnston struct cryptop *crp; 1290b356ddf0SMark Johnston struct safexcel_context_record *ctx; 1291b356ddf0SMark Johnston struct safexcel_session *sess; 1292b356ddf0SMark Johnston uint8_t *data; 1293b356ddf0SMark Johnston int off; 1294b356ddf0SMark Johnston 1295b356ddf0SMark Johnston crp = req->crp; 1296b356ddf0SMark Johnston csp = crypto_get_params(crp->crp_session); 1297b356ddf0SMark Johnston sess = req->sess; 1298b356ddf0SMark Johnston 1299b356ddf0SMark Johnston ctx = (struct safexcel_context_record *)req->ctx.vaddr; 1300b356ddf0SMark Johnston data = (uint8_t *)ctx->data; 1301b356ddf0SMark Johnston if (csp->csp_cipher_alg != 0) { 1302b356ddf0SMark Johnston if (crp->crp_cipher_key != NULL) 1303b356ddf0SMark Johnston memcpy(data, crp->crp_cipher_key, sess->klen); 1304b356ddf0SMark Johnston else 1305b356ddf0SMark Johnston memcpy(data, csp->csp_cipher_key, sess->klen); 1306b356ddf0SMark Johnston off = sess->klen; 1307b356ddf0SMark Johnston } else if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC) { 1308b356ddf0SMark Johnston if (crp->crp_auth_key != NULL) 1309b356ddf0SMark Johnston memcpy(data, crp->crp_auth_key, sess->klen); 1310b356ddf0SMark Johnston else 1311b356ddf0SMark Johnston memcpy(data, csp->csp_auth_key, sess->klen); 1312b356ddf0SMark Johnston off = sess->klen; 1313b356ddf0SMark Johnston } else { 1314b356ddf0SMark Johnston off = 0; 1315b356ddf0SMark Johnston } 1316b356ddf0SMark Johnston 1317b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 1318b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 1319b356ddf0SMark Johnston memcpy(data + off, sess->ghash_key, GMAC_BLOCK_LEN); 1320b356ddf0SMark Johnston off += GMAC_BLOCK_LEN; 1321b356ddf0SMark Johnston break; 1322b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 1323b356ddf0SMark Johnston memcpy(data + off, sess->xcbc_key, 1324b356ddf0SMark Johnston AES_BLOCK_LEN * 2 + sess->klen); 1325b356ddf0SMark Johnston off += AES_BLOCK_LEN * 2 + sess->klen; 1326b356ddf0SMark Johnston break; 1327b356ddf0SMark Johnston case CRYPTO_AES_XTS: 1328b356ddf0SMark Johnston memcpy(data + off, sess->tweak_key, sess->klen); 1329b356ddf0SMark Johnston off += sess->klen; 1330b356ddf0SMark Johnston break; 1331b356ddf0SMark Johnston } 1332b356ddf0SMark Johnston 1333b356ddf0SMark Johnston switch (csp->csp_auth_alg) { 1334b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 1335b356ddf0SMark Johnston memcpy(data + off, sess->ghash_key, GMAC_BLOCK_LEN); 1336b356ddf0SMark Johnston off += GMAC_BLOCK_LEN; 1337b356ddf0SMark Johnston break; 1338b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 1339b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 1340b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 1341b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 1342b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 1343b356ddf0SMark Johnston memcpy(data + off, sess->hmac_ipad, sess->statelen); 1344b356ddf0SMark Johnston off += sess->statelen; 1345b356ddf0SMark Johnston memcpy(data + off, sess->hmac_opad, sess->statelen); 1346b356ddf0SMark Johnston off += sess->statelen; 1347b356ddf0SMark Johnston break; 1348b356ddf0SMark Johnston } 1349b356ddf0SMark Johnston 1350b356ddf0SMark Johnston return (off); 1351b356ddf0SMark Johnston } 1352b356ddf0SMark Johnston 1353b356ddf0SMark Johnston /* 1354b356ddf0SMark Johnston * Populate fields in the first command descriptor of the chain used to encode 1355b356ddf0SMark Johnston * the specified request. These fields indicate the algorithms used, the size 1356b356ddf0SMark Johnston * of the key material stored in the associated context record, the primitive 1357b356ddf0SMark Johnston * operations to be performed on input data, and the location of the IV if any. 1358b356ddf0SMark Johnston */ 1359b356ddf0SMark Johnston static void 1360b356ddf0SMark Johnston safexcel_set_command(struct safexcel_request *req, 1361b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc) 1362b356ddf0SMark Johnston { 1363b356ddf0SMark Johnston const struct crypto_session_params *csp; 1364b356ddf0SMark Johnston struct cryptop *crp; 1365b356ddf0SMark Johnston struct safexcel_session *sess; 1366b356ddf0SMark Johnston uint32_t ctrl0, ctrl1, ctxr_len; 1367b356ddf0SMark Johnston int alg; 1368b356ddf0SMark Johnston 1369b356ddf0SMark Johnston crp = req->crp; 1370b356ddf0SMark Johnston csp = crypto_get_params(crp->crp_session); 1371b356ddf0SMark Johnston sess = req->sess; 1372b356ddf0SMark Johnston 1373b356ddf0SMark Johnston ctrl0 = sess->alg | sess->digest | sess->hash; 1374b356ddf0SMark Johnston ctrl1 = sess->mode; 1375b356ddf0SMark Johnston 1376b356ddf0SMark Johnston ctxr_len = safexcel_set_context(req) / sizeof(uint32_t); 1377b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_SIZE(ctxr_len); 1378b356ddf0SMark Johnston 1379b356ddf0SMark Johnston alg = csp->csp_cipher_alg; 1380b356ddf0SMark Johnston if (alg == 0) 1381b356ddf0SMark Johnston alg = csp->csp_auth_alg; 1382b356ddf0SMark Johnston 1383b356ddf0SMark Johnston switch (alg) { 1384b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 1385b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1386b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_HASH_ENCRYPT_OUT | 1387b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN; 1388b356ddf0SMark Johnston } else { 1389b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_DECRYPT_HASH_IN | 1390b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN; 1391b356ddf0SMark Johnston } 1392b356ddf0SMark Johnston ctrl1 |= SAFEXCEL_CONTROL1_IV0 | SAFEXCEL_CONTROL1_IV1 | 1393b356ddf0SMark Johnston SAFEXCEL_CONTROL1_IV2 | SAFEXCEL_CONTROL1_IV3; 1394b356ddf0SMark Johnston break; 1395b356ddf0SMark Johnston case CRYPTO_AES_CBC: 1396b356ddf0SMark Johnston case CRYPTO_AES_ICM: 1397b356ddf0SMark Johnston case CRYPTO_AES_XTS: 1398b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 1399b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_CRYPTO_OUT | 1400b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN; 1401b356ddf0SMark Johnston if (csp->csp_auth_alg != 0) 1402b356ddf0SMark Johnston ctrl0 |= 1403b356ddf0SMark Johnston SAFEXCEL_CONTROL0_TYPE_ENCRYPT_HASH_OUT; 1404b356ddf0SMark Johnston } else { 1405b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_CRYPTO_IN | 1406b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN; 1407b356ddf0SMark Johnston if (csp->csp_auth_alg != 0) 1408b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_HASH_DECRYPT_IN; 1409b356ddf0SMark Johnston } 1410b356ddf0SMark Johnston break; 1411b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 1412b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 1413b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op) || 1414b356ddf0SMark Johnston csp->csp_auth_alg != 0) { 1415b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_CRYPTO_OUT | 1416b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN | 1417b356ddf0SMark Johnston SAFEXCEL_CONTROL0_TYPE_HASH_OUT; 1418b356ddf0SMark Johnston } else { 1419b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_CRYPTO_IN | 1420b356ddf0SMark Johnston SAFEXCEL_CONTROL0_KEY_EN | 1421b356ddf0SMark Johnston SAFEXCEL_CONTROL0_TYPE_HASH_DECRYPT_IN; 1422b356ddf0SMark Johnston } 1423b356ddf0SMark Johnston if (csp->csp_cipher_alg == CRYPTO_AES_NIST_GCM_16) { 1424b356ddf0SMark Johnston ctrl1 |= SAFEXCEL_CONTROL1_COUNTER_MODE | 1425b356ddf0SMark Johnston SAFEXCEL_CONTROL1_IV0 | SAFEXCEL_CONTROL1_IV1 | 1426b356ddf0SMark Johnston SAFEXCEL_CONTROL1_IV2; 1427b356ddf0SMark Johnston } 1428b356ddf0SMark Johnston break; 1429b356ddf0SMark Johnston case CRYPTO_SHA1: 1430b356ddf0SMark Johnston case CRYPTO_SHA2_224: 1431b356ddf0SMark Johnston case CRYPTO_SHA2_256: 1432b356ddf0SMark Johnston case CRYPTO_SHA2_384: 1433b356ddf0SMark Johnston case CRYPTO_SHA2_512: 1434b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_RESTART_HASH; 1435b356ddf0SMark Johnston /* FALLTHROUGH */ 1436b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 1437b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 1438b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 1439b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 1440b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 1441b356ddf0SMark Johnston ctrl0 |= SAFEXCEL_CONTROL0_TYPE_HASH_OUT; 1442b356ddf0SMark Johnston break; 1443b356ddf0SMark Johnston } 1444b356ddf0SMark Johnston 1445b356ddf0SMark Johnston cdesc->control_data.control0 = ctrl0; 1446b356ddf0SMark Johnston cdesc->control_data.control1 = ctrl1; 1447b356ddf0SMark Johnston } 1448b356ddf0SMark Johnston 1449b356ddf0SMark Johnston /* 1450b356ddf0SMark Johnston * Construct a no-op instruction, used to pad input tokens. 1451b356ddf0SMark Johnston */ 1452b356ddf0SMark Johnston static void 1453b356ddf0SMark Johnston safexcel_instr_nop(struct safexcel_instr **instrp) 1454b356ddf0SMark Johnston { 1455b356ddf0SMark Johnston struct safexcel_instr *instr; 1456b356ddf0SMark Johnston 1457b356ddf0SMark Johnston instr = *instrp; 1458b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1459b356ddf0SMark Johnston instr->length = (1 << 2); 1460b356ddf0SMark Johnston instr->status = 0; 1461b356ddf0SMark Johnston instr->instructions = 0; 1462b356ddf0SMark Johnston 1463b356ddf0SMark Johnston *instrp = instr + 1; 1464b356ddf0SMark Johnston } 1465b356ddf0SMark Johnston 1466b356ddf0SMark Johnston /* 1467b356ddf0SMark Johnston * Insert the digest of the input payload. This is typically the last 1468b356ddf0SMark Johnston * instruction of a sequence. 1469b356ddf0SMark Johnston */ 1470b356ddf0SMark Johnston static void 1471b356ddf0SMark Johnston safexcel_instr_insert_digest(struct safexcel_instr **instrp, int len) 1472b356ddf0SMark Johnston { 1473b356ddf0SMark Johnston struct safexcel_instr *instr; 1474b356ddf0SMark Johnston 1475b356ddf0SMark Johnston instr = *instrp; 1476b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1477b356ddf0SMark Johnston instr->length = len; 1478b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH | 1479b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_PACKET; 1480b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_OUTPUT | 1481b356ddf0SMark Johnston SAFEXCEL_INSTR_INSERT_HASH_DIGEST; 1482b356ddf0SMark Johnston 1483b356ddf0SMark Johnston *instrp = instr + 1; 1484b356ddf0SMark Johnston } 1485b356ddf0SMark Johnston 1486b356ddf0SMark Johnston /* 1487b356ddf0SMark Johnston * Retrieve and verify a digest. 1488b356ddf0SMark Johnston */ 1489b356ddf0SMark Johnston static void 1490b356ddf0SMark Johnston safexcel_instr_retrieve_digest(struct safexcel_instr **instrp, int len) 1491b356ddf0SMark Johnston { 1492b356ddf0SMark Johnston struct safexcel_instr *instr; 1493b356ddf0SMark Johnston 1494b356ddf0SMark Johnston instr = *instrp; 1495b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_RETRIEVE; 1496b356ddf0SMark Johnston instr->length = len; 1497b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH | 1498b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_PACKET; 1499b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INSERT_HASH_DIGEST; 1500b356ddf0SMark Johnston instr++; 1501b356ddf0SMark Johnston 1502b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_VERIFY_FIELDS; 1503b356ddf0SMark Johnston instr->length = len | SAFEXCEL_INSTR_VERIFY_HASH; 1504b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH | 1505b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_PACKET; 1506b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_VERIFY_PADDING; 1507b356ddf0SMark Johnston 1508b356ddf0SMark Johnston *instrp = instr + 1; 1509b356ddf0SMark Johnston } 1510b356ddf0SMark Johnston 1511b356ddf0SMark Johnston static void 1512b356ddf0SMark Johnston safexcel_instr_temp_aes_block(struct safexcel_instr **instrp) 1513b356ddf0SMark Johnston { 1514b356ddf0SMark Johnston struct safexcel_instr *instr; 1515b356ddf0SMark Johnston 1516b356ddf0SMark Johnston instr = *instrp; 1517b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT_REMOVE_RESULT; 1518b356ddf0SMark Johnston instr->length = 0; 1519b356ddf0SMark Johnston instr->status = 0; 1520b356ddf0SMark Johnston instr->instructions = AES_BLOCK_LEN; 1521b356ddf0SMark Johnston instr++; 1522b356ddf0SMark Johnston 1523b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1524b356ddf0SMark Johnston instr->length = AES_BLOCK_LEN; 1525b356ddf0SMark Johnston instr->status = 0; 1526b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_OUTPUT | 1527b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_CRYPTO; 1528b356ddf0SMark Johnston 1529b356ddf0SMark Johnston *instrp = instr + 1; 1530b356ddf0SMark Johnston } 1531b356ddf0SMark Johnston 1532b356ddf0SMark Johnston /* 1533b356ddf0SMark Johnston * Handle a request for an unauthenticated block cipher. 1534b356ddf0SMark Johnston */ 1535b356ddf0SMark Johnston static void 1536b356ddf0SMark Johnston safexcel_instr_cipher(struct safexcel_request *req, 1537b356ddf0SMark Johnston struct safexcel_instr *instr, struct safexcel_cmd_descr *cdesc) 1538b356ddf0SMark Johnston { 1539b356ddf0SMark Johnston struct cryptop *crp; 1540b356ddf0SMark Johnston 1541b356ddf0SMark Johnston crp = req->crp; 1542b356ddf0SMark Johnston 1543b356ddf0SMark Johnston /* Insert the payload. */ 1544b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1545b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1546b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_PACKET | 1547b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_HASH; 1548b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INS_LAST | 1549b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_CRYPTO | SAFEXCEL_INSTR_DEST_OUTPUT; 1550b356ddf0SMark Johnston 1551b356ddf0SMark Johnston cdesc->additional_cdata_size = 1; 1552b356ddf0SMark Johnston } 1553b356ddf0SMark Johnston 1554b356ddf0SMark Johnston static void 1555b356ddf0SMark Johnston safexcel_instr_eta(struct safexcel_request *req, struct safexcel_instr *instr, 1556b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc) 1557b356ddf0SMark Johnston { 1558b356ddf0SMark Johnston const struct crypto_session_params *csp; 1559b356ddf0SMark Johnston struct cryptop *crp; 1560b356ddf0SMark Johnston struct safexcel_instr *start; 1561b356ddf0SMark Johnston 1562b356ddf0SMark Johnston crp = req->crp; 1563b356ddf0SMark Johnston csp = crypto_get_params(crp->crp_session); 1564b356ddf0SMark Johnston start = instr; 1565b356ddf0SMark Johnston 1566b356ddf0SMark Johnston /* Insert the AAD. */ 1567b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1568b356ddf0SMark Johnston instr->length = crp->crp_aad_length; 1569b356ddf0SMark Johnston instr->status = crp->crp_payload_length == 0 ? 1570b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_HASH : 0; 1571b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INS_LAST | 1572b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_HASH; 1573b356ddf0SMark Johnston instr++; 1574b356ddf0SMark Johnston 1575b356ddf0SMark Johnston /* Encrypt any data left in the request. */ 1576b356ddf0SMark Johnston if (crp->crp_payload_length > 0) { 1577b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1578b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1579b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH; 1580b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INS_LAST | 1581b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_CRYPTO | 1582b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_HASH | 1583b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_OUTPUT; 1584b356ddf0SMark Johnston instr++; 1585b356ddf0SMark Johnston } 1586b356ddf0SMark Johnston 1587b356ddf0SMark Johnston /* 1588b356ddf0SMark Johnston * Compute the digest, or extract it and place it in the output stream. 1589b356ddf0SMark Johnston */ 1590b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 1591b356ddf0SMark Johnston safexcel_instr_insert_digest(&instr, req->sess->digestlen); 1592b356ddf0SMark Johnston else 1593b356ddf0SMark Johnston safexcel_instr_retrieve_digest(&instr, req->sess->digestlen); 1594b356ddf0SMark Johnston cdesc->additional_cdata_size = instr - start; 1595b356ddf0SMark Johnston } 1596b356ddf0SMark Johnston 1597b356ddf0SMark Johnston static void 1598b356ddf0SMark Johnston safexcel_instr_sha_hash(struct safexcel_request *req, 1599b356ddf0SMark Johnston struct safexcel_instr *instr) 1600b356ddf0SMark Johnston { 1601b356ddf0SMark Johnston struct cryptop *crp; 1602b356ddf0SMark Johnston struct safexcel_instr *start; 1603b356ddf0SMark Johnston 1604b356ddf0SMark Johnston crp = req->crp; 1605b356ddf0SMark Johnston start = instr; 1606b356ddf0SMark Johnston 1607b356ddf0SMark Johnston /* Pass the input data to the hash engine. */ 1608b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1609b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1610b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH; 1611b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_HASH; 1612b356ddf0SMark Johnston instr++; 1613b356ddf0SMark Johnston 1614b356ddf0SMark Johnston /* Insert the hash result into the output stream. */ 1615b356ddf0SMark Johnston safexcel_instr_insert_digest(&instr, req->sess->digestlen); 1616b356ddf0SMark Johnston 1617b356ddf0SMark Johnston /* Pad the rest of the inline instruction space. */ 1618b356ddf0SMark Johnston while (instr != start + SAFEXCEL_MAX_ITOKENS) 1619b356ddf0SMark Johnston safexcel_instr_nop(&instr); 1620b356ddf0SMark Johnston } 1621b356ddf0SMark Johnston 1622b356ddf0SMark Johnston static void 1623b356ddf0SMark Johnston safexcel_instr_ccm(struct safexcel_request *req, struct safexcel_instr *instr, 1624b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc) 1625b356ddf0SMark Johnston { 1626b356ddf0SMark Johnston struct cryptop *crp; 1627b356ddf0SMark Johnston struct safexcel_instr *start; 1628b356ddf0SMark Johnston uint8_t *a0, *b0, *alenp, L; 1629b356ddf0SMark Johnston int aalign, blen; 1630b356ddf0SMark Johnston 1631b356ddf0SMark Johnston crp = req->crp; 1632b356ddf0SMark Johnston start = instr; 1633b356ddf0SMark Johnston 1634b356ddf0SMark Johnston /* 1635b356ddf0SMark Johnston * Construct two blocks, A0 and B0, used in encryption and 1636b356ddf0SMark Johnston * authentication, respectively. A0 is embedded in the token 1637b356ddf0SMark Johnston * descriptor, and B0 is inserted directly into the data stream using 1638b356ddf0SMark Johnston * instructions below. 1639b356ddf0SMark Johnston * 1640b356ddf0SMark Johnston * OCF seems to assume a 12-byte IV, fixing L (the payload length size) 1641b356ddf0SMark Johnston * at 3 bytes due to the layout of B0. This is fine since the driver 1642b356ddf0SMark Johnston * has a maximum of 65535 bytes anyway. 1643b356ddf0SMark Johnston */ 1644b356ddf0SMark Johnston blen = AES_BLOCK_LEN; 1645b356ddf0SMark Johnston L = 3; 1646b356ddf0SMark Johnston 1647b356ddf0SMark Johnston a0 = (uint8_t *)&cdesc->control_data.token[0]; 1648b356ddf0SMark Johnston memset(a0, 0, blen); 1649b356ddf0SMark Johnston a0[0] = L - 1; 1650b356ddf0SMark Johnston memcpy(&a0[1], req->iv, AES_CCM_IV_LEN); 1651b356ddf0SMark Johnston 1652b356ddf0SMark Johnston /* 1653b356ddf0SMark Johnston * Insert B0 and the AAD length into the input stream. 1654b356ddf0SMark Johnston */ 1655b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1656b356ddf0SMark Johnston instr->length = blen + (crp->crp_aad_length > 0 ? 2 : 0); 1657b356ddf0SMark Johnston instr->status = 0; 1658b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_HASH | 1659b356ddf0SMark Johnston SAFEXCEL_INSTR_INSERT_IMMEDIATE; 1660b356ddf0SMark Johnston instr++; 1661b356ddf0SMark Johnston 1662b356ddf0SMark Johnston b0 = (uint8_t *)instr; 1663b356ddf0SMark Johnston memset(b0, 0, blen); 1664b356ddf0SMark Johnston b0[0] = 166509676137SLi-Wen Hsu (L - 1) | /* payload length size */ 1666b356ddf0SMark Johnston ((CCM_CBC_MAX_DIGEST_LEN - 2) / 2) << 3 /* digest length */ | 1667b356ddf0SMark Johnston (crp->crp_aad_length > 0 ? 1 : 0) << 6 /* AAD present bit */; 1668b356ddf0SMark Johnston memcpy(&b0[1], req->iv, AES_CCM_IV_LEN); 1669b356ddf0SMark Johnston b0[14] = crp->crp_payload_length >> 8; 1670b356ddf0SMark Johnston b0[15] = crp->crp_payload_length & 0xff; 1671b356ddf0SMark Johnston instr += blen / sizeof(*instr); 1672b356ddf0SMark Johnston 1673b356ddf0SMark Johnston /* Insert the AAD length and data into the input stream. */ 1674b356ddf0SMark Johnston if (crp->crp_aad_length > 0) { 1675b356ddf0SMark Johnston alenp = (uint8_t *)instr; 1676b356ddf0SMark Johnston alenp[0] = crp->crp_aad_length >> 8; 1677b356ddf0SMark Johnston alenp[1] = crp->crp_aad_length & 0xff; 1678b356ddf0SMark Johnston alenp[2] = 0; 1679b356ddf0SMark Johnston alenp[3] = 0; 1680b356ddf0SMark Johnston instr++; 1681b356ddf0SMark Johnston 1682b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1683b356ddf0SMark Johnston instr->length = crp->crp_aad_length; 1684b356ddf0SMark Johnston instr->status = 0; 1685b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_HASH; 1686b356ddf0SMark Johnston instr++; 1687b356ddf0SMark Johnston 1688b356ddf0SMark Johnston /* Insert zero padding. */ 1689b356ddf0SMark Johnston aalign = (crp->crp_aad_length + 2) & (blen - 1); 1690b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1691b356ddf0SMark Johnston instr->length = aalign == 0 ? 0 : 1692b356ddf0SMark Johnston blen - ((crp->crp_aad_length + 2) & (blen - 1)); 1693b356ddf0SMark Johnston instr->status = crp->crp_payload_length == 0 ? 1694b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_HASH : 0; 1695b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_HASH; 1696b356ddf0SMark Johnston instr++; 1697b356ddf0SMark Johnston } 1698b356ddf0SMark Johnston 1699b356ddf0SMark Johnston safexcel_instr_temp_aes_block(&instr); 1700b356ddf0SMark Johnston 1701b356ddf0SMark Johnston /* Insert the cipher payload into the input stream. */ 1702b356ddf0SMark Johnston if (crp->crp_payload_length > 0) { 1703b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1704b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1705b356ddf0SMark Johnston instr->status = (crp->crp_payload_length & (blen - 1)) == 0 ? 1706b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_HASH : 0; 1707b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_OUTPUT | 1708b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_CRYPTO | 1709b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_HASH | 1710b356ddf0SMark Johnston SAFEXCEL_INSTR_INS_LAST; 1711b356ddf0SMark Johnston instr++; 1712b356ddf0SMark Johnston 1713b356ddf0SMark Johnston /* Insert zero padding. */ 1714b356ddf0SMark Johnston if (crp->crp_payload_length & (blen - 1)) { 1715b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_INSERT; 1716b356ddf0SMark Johnston instr->length = blen - 1717b356ddf0SMark Johnston (crp->crp_payload_length & (blen - 1)); 1718b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH; 1719b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_HASH; 1720b356ddf0SMark Johnston instr++; 1721b356ddf0SMark Johnston } 1722b356ddf0SMark Johnston } 1723b356ddf0SMark Johnston 1724b356ddf0SMark Johnston /* 1725b356ddf0SMark Johnston * Compute the digest, or extract it and place it in the output stream. 1726b356ddf0SMark Johnston */ 1727b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 1728b356ddf0SMark Johnston safexcel_instr_insert_digest(&instr, req->sess->digestlen); 1729b356ddf0SMark Johnston else 1730b356ddf0SMark Johnston safexcel_instr_retrieve_digest(&instr, req->sess->digestlen); 1731b356ddf0SMark Johnston 1732b356ddf0SMark Johnston cdesc->additional_cdata_size = instr - start; 1733b356ddf0SMark Johnston } 1734b356ddf0SMark Johnston 1735b356ddf0SMark Johnston static void 1736b356ddf0SMark Johnston safexcel_instr_gcm(struct safexcel_request *req, struct safexcel_instr *instr, 1737b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc) 1738b356ddf0SMark Johnston { 1739b356ddf0SMark Johnston struct cryptop *crp; 1740b356ddf0SMark Johnston struct safexcel_instr *start; 1741b356ddf0SMark Johnston 1742b356ddf0SMark Johnston memcpy(cdesc->control_data.token, req->iv, AES_GCM_IV_LEN); 1743b356ddf0SMark Johnston cdesc->control_data.token[3] = htobe32(1); 1744b356ddf0SMark Johnston 1745b356ddf0SMark Johnston crp = req->crp; 1746b356ddf0SMark Johnston start = instr; 1747b356ddf0SMark Johnston 1748b356ddf0SMark Johnston /* Insert the AAD into the input stream. */ 1749b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1750b356ddf0SMark Johnston instr->length = crp->crp_aad_length; 1751b356ddf0SMark Johnston instr->status = crp->crp_payload_length == 0 ? 1752b356ddf0SMark Johnston SAFEXCEL_INSTR_STATUS_LAST_HASH : 0; 1753b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INS_LAST | 1754b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_HASH; 1755b356ddf0SMark Johnston instr++; 1756b356ddf0SMark Johnston 1757b356ddf0SMark Johnston safexcel_instr_temp_aes_block(&instr); 1758b356ddf0SMark Johnston 1759b356ddf0SMark Johnston /* Insert the cipher payload into the input stream. */ 1760b356ddf0SMark Johnston if (crp->crp_payload_length > 0) { 1761b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1762b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1763b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH; 1764b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_DEST_OUTPUT | 1765b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_CRYPTO | SAFEXCEL_INSTR_DEST_HASH | 1766b356ddf0SMark Johnston SAFEXCEL_INSTR_INS_LAST; 1767b356ddf0SMark Johnston instr++; 1768b356ddf0SMark Johnston } 1769b356ddf0SMark Johnston 1770b356ddf0SMark Johnston /* 1771b356ddf0SMark Johnston * Compute the digest, or extract it and place it in the output stream. 1772b356ddf0SMark Johnston */ 1773b356ddf0SMark Johnston if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) 1774b356ddf0SMark Johnston safexcel_instr_insert_digest(&instr, req->sess->digestlen); 1775b356ddf0SMark Johnston else 1776b356ddf0SMark Johnston safexcel_instr_retrieve_digest(&instr, req->sess->digestlen); 1777b356ddf0SMark Johnston 1778b356ddf0SMark Johnston cdesc->additional_cdata_size = instr - start; 1779b356ddf0SMark Johnston } 1780b356ddf0SMark Johnston 1781b356ddf0SMark Johnston static void 1782b356ddf0SMark Johnston safexcel_instr_gmac(struct safexcel_request *req, struct safexcel_instr *instr, 1783b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc) 1784b356ddf0SMark Johnston { 1785b356ddf0SMark Johnston struct cryptop *crp; 1786b356ddf0SMark Johnston struct safexcel_instr *start; 1787b356ddf0SMark Johnston 1788b356ddf0SMark Johnston memcpy(cdesc->control_data.token, req->iv, AES_GCM_IV_LEN); 1789b356ddf0SMark Johnston cdesc->control_data.token[3] = htobe32(1); 1790b356ddf0SMark Johnston 1791b356ddf0SMark Johnston crp = req->crp; 1792b356ddf0SMark Johnston start = instr; 1793b356ddf0SMark Johnston 1794b356ddf0SMark Johnston instr->opcode = SAFEXCEL_INSTR_OPCODE_DIRECTION; 1795b356ddf0SMark Johnston instr->length = crp->crp_payload_length; 1796b356ddf0SMark Johnston instr->status = SAFEXCEL_INSTR_STATUS_LAST_HASH; 1797b356ddf0SMark Johnston instr->instructions = SAFEXCEL_INSTR_INS_LAST | 1798b356ddf0SMark Johnston SAFEXCEL_INSTR_DEST_HASH; 1799b356ddf0SMark Johnston instr++; 1800b356ddf0SMark Johnston 1801b356ddf0SMark Johnston safexcel_instr_temp_aes_block(&instr); 1802b356ddf0SMark Johnston 1803b356ddf0SMark Johnston safexcel_instr_insert_digest(&instr, req->sess->digestlen); 1804b356ddf0SMark Johnston 1805b356ddf0SMark Johnston cdesc->additional_cdata_size = instr - start; 1806b356ddf0SMark Johnston } 1807b356ddf0SMark Johnston 1808b356ddf0SMark Johnston static void 1809b356ddf0SMark Johnston safexcel_set_token(struct safexcel_request *req) 1810b356ddf0SMark Johnston { 1811b356ddf0SMark Johnston const struct crypto_session_params *csp; 1812b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 1813b356ddf0SMark Johnston struct safexcel_instr *instr; 1814b356ddf0SMark Johnston struct safexcel_softc *sc; 1815b356ddf0SMark Johnston int ringidx; 1816b356ddf0SMark Johnston 1817b356ddf0SMark Johnston csp = crypto_get_params(req->crp->crp_session); 1818b356ddf0SMark Johnston cdesc = req->cdesc; 1819b356ddf0SMark Johnston sc = req->sc; 1820e934d455SMark Johnston ringidx = req->ringidx; 1821b356ddf0SMark Johnston 1822b356ddf0SMark Johnston safexcel_set_command(req, cdesc); 1823b356ddf0SMark Johnston 1824b356ddf0SMark Johnston /* 1825b356ddf0SMark Johnston * For keyless hash operations, the token instructions can be embedded 1826b356ddf0SMark Johnston * in the token itself. Otherwise we use an additional token descriptor 1827b356ddf0SMark Johnston * and the embedded instruction space is used to store the IV. 1828b356ddf0SMark Johnston */ 1829b356ddf0SMark Johnston if (csp->csp_cipher_alg == 0 && 1830b356ddf0SMark Johnston csp->csp_auth_alg != CRYPTO_AES_NIST_GMAC) { 1831b356ddf0SMark Johnston instr = (void *)cdesc->control_data.token; 1832b356ddf0SMark Johnston } else { 1833b356ddf0SMark Johnston instr = (void *)(sc->sc_ring[ringidx].dma_atok.vaddr + 1834b356ddf0SMark Johnston sc->sc_config.atok_offset * 1835b356ddf0SMark Johnston (cdesc - sc->sc_ring[ringidx].cdr.desc)); 1836b356ddf0SMark Johnston cdesc->control_data.options |= SAFEXCEL_OPTION_4_TOKEN_IV_CMD; 1837b356ddf0SMark Johnston } 1838b356ddf0SMark Johnston 1839b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 1840b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 1841b356ddf0SMark Johnston safexcel_instr_gcm(req, instr, cdesc); 1842b356ddf0SMark Johnston break; 1843b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 1844b356ddf0SMark Johnston safexcel_instr_ccm(req, instr, cdesc); 1845b356ddf0SMark Johnston break; 1846b356ddf0SMark Johnston case CRYPTO_AES_XTS: 1847b356ddf0SMark Johnston memcpy(cdesc->control_data.token, req->iv, AES_XTS_IV_LEN); 1848b356ddf0SMark Johnston memset(cdesc->control_data.token + 1849b356ddf0SMark Johnston AES_XTS_IV_LEN / sizeof(uint32_t), 0, AES_XTS_IV_LEN); 1850b356ddf0SMark Johnston 1851b356ddf0SMark Johnston safexcel_instr_cipher(req, instr, cdesc); 1852b356ddf0SMark Johnston break; 1853b356ddf0SMark Johnston case CRYPTO_AES_CBC: 1854b356ddf0SMark Johnston case CRYPTO_AES_ICM: 1855b356ddf0SMark Johnston memcpy(cdesc->control_data.token, req->iv, AES_BLOCK_LEN); 1856b356ddf0SMark Johnston if (csp->csp_auth_alg != 0) 1857b356ddf0SMark Johnston safexcel_instr_eta(req, instr, cdesc); 1858b356ddf0SMark Johnston else 1859b356ddf0SMark Johnston safexcel_instr_cipher(req, instr, cdesc); 1860b356ddf0SMark Johnston break; 1861b356ddf0SMark Johnston default: 1862b356ddf0SMark Johnston switch (csp->csp_auth_alg) { 1863b356ddf0SMark Johnston case CRYPTO_SHA1: 1864b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 1865b356ddf0SMark Johnston case CRYPTO_SHA2_224: 1866b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 1867b356ddf0SMark Johnston case CRYPTO_SHA2_256: 1868b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 1869b356ddf0SMark Johnston case CRYPTO_SHA2_384: 1870b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 1871b356ddf0SMark Johnston case CRYPTO_SHA2_512: 1872b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 1873b356ddf0SMark Johnston safexcel_instr_sha_hash(req, instr); 1874b356ddf0SMark Johnston break; 1875b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 1876b356ddf0SMark Johnston safexcel_instr_gmac(req, instr, cdesc); 1877b356ddf0SMark Johnston break; 1878b356ddf0SMark Johnston default: 1879b356ddf0SMark Johnston panic("unhandled auth request %d", csp->csp_auth_alg); 1880b356ddf0SMark Johnston } 1881b356ddf0SMark Johnston break; 1882b356ddf0SMark Johnston } 1883b356ddf0SMark Johnston } 1884b356ddf0SMark Johnston 1885b356ddf0SMark Johnston static struct safexcel_res_descr * 1886b356ddf0SMark Johnston safexcel_res_descr_add(struct safexcel_ring *ring, bool first, bool last, 1887b356ddf0SMark Johnston bus_addr_t data, uint32_t len) 1888b356ddf0SMark Johnston { 1889b356ddf0SMark Johnston struct safexcel_res_descr *rdesc; 1890b356ddf0SMark Johnston struct safexcel_res_descr_ring *rring; 1891b356ddf0SMark Johnston 1892b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 1893b356ddf0SMark Johnston 1894b356ddf0SMark Johnston rring = &ring->rdr; 1895b356ddf0SMark Johnston if ((rring->write + 1) % SAFEXCEL_RING_SIZE == rring->read) 1896b356ddf0SMark Johnston return (NULL); 1897b356ddf0SMark Johnston 1898b356ddf0SMark Johnston rdesc = &rring->desc[rring->write]; 1899b356ddf0SMark Johnston rring->write = (rring->write + 1) % SAFEXCEL_RING_SIZE; 1900b356ddf0SMark Johnston 1901b356ddf0SMark Johnston rdesc->particle_size = len; 1902b356ddf0SMark Johnston rdesc->rsvd0 = 0; 1903b356ddf0SMark Johnston rdesc->descriptor_overflow = 0; 1904b356ddf0SMark Johnston rdesc->buffer_overflow = 0; 1905b356ddf0SMark Johnston rdesc->last_seg = last; 1906b356ddf0SMark Johnston rdesc->first_seg = first; 1907b356ddf0SMark Johnston rdesc->result_size = 1908b356ddf0SMark Johnston sizeof(struct safexcel_res_data) / sizeof(uint32_t); 1909b356ddf0SMark Johnston rdesc->rsvd1 = 0; 1910b356ddf0SMark Johnston rdesc->data_lo = SAFEXCEL_ADDR_LO(data); 1911b356ddf0SMark Johnston rdesc->data_hi = SAFEXCEL_ADDR_HI(data); 1912b356ddf0SMark Johnston 1913b356ddf0SMark Johnston if (first) { 1914b356ddf0SMark Johnston rdesc->result_data.packet_length = 0; 1915b356ddf0SMark Johnston rdesc->result_data.error_code = 0; 1916b356ddf0SMark Johnston } 1917b356ddf0SMark Johnston 1918b356ddf0SMark Johnston return (rdesc); 1919b356ddf0SMark Johnston } 1920b356ddf0SMark Johnston 1921b356ddf0SMark Johnston static struct safexcel_cmd_descr * 1922b356ddf0SMark Johnston safexcel_cmd_descr_add(struct safexcel_ring *ring, bool first, bool last, 1923b356ddf0SMark Johnston bus_addr_t data, uint32_t seglen, uint32_t reqlen, bus_addr_t context) 1924b356ddf0SMark Johnston { 1925b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 1926b356ddf0SMark Johnston struct safexcel_cmd_descr_ring *cring; 1927b356ddf0SMark Johnston 19283db2b0d5SMark Johnston KASSERT(reqlen <= SAFEXCEL_MAX_REQUEST_SIZE, 19293db2b0d5SMark Johnston ("%s: request length %u too long", __func__, reqlen)); 1930b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 1931b356ddf0SMark Johnston 1932b356ddf0SMark Johnston cring = &ring->cdr; 1933b356ddf0SMark Johnston if ((cring->write + 1) % SAFEXCEL_RING_SIZE == cring->read) 1934b356ddf0SMark Johnston return (NULL); 1935b356ddf0SMark Johnston 1936b356ddf0SMark Johnston cdesc = &cring->desc[cring->write]; 1937b356ddf0SMark Johnston cring->write = (cring->write + 1) % SAFEXCEL_RING_SIZE; 1938b356ddf0SMark Johnston 1939b356ddf0SMark Johnston cdesc->particle_size = seglen; 1940b356ddf0SMark Johnston cdesc->rsvd0 = 0; 1941b356ddf0SMark Johnston cdesc->last_seg = last; 1942b356ddf0SMark Johnston cdesc->first_seg = first; 1943b356ddf0SMark Johnston cdesc->additional_cdata_size = 0; 1944b356ddf0SMark Johnston cdesc->rsvd1 = 0; 1945b356ddf0SMark Johnston cdesc->data_lo = SAFEXCEL_ADDR_LO(data); 1946b356ddf0SMark Johnston cdesc->data_hi = SAFEXCEL_ADDR_HI(data); 1947b356ddf0SMark Johnston if (first) { 1948b356ddf0SMark Johnston cdesc->control_data.packet_length = reqlen; 1949b356ddf0SMark Johnston cdesc->control_data.options = SAFEXCEL_OPTION_IP | 1950b356ddf0SMark Johnston SAFEXCEL_OPTION_CP | SAFEXCEL_OPTION_CTX_CTRL_IN_CMD | 1951b356ddf0SMark Johnston SAFEXCEL_OPTION_RC_AUTO; 1952b356ddf0SMark Johnston cdesc->control_data.type = SAFEXCEL_TOKEN_TYPE_BYPASS; 1953b356ddf0SMark Johnston cdesc->control_data.context_lo = SAFEXCEL_ADDR_LO(context) | 1954b356ddf0SMark Johnston SAFEXCEL_CONTEXT_SMALL; 1955b356ddf0SMark Johnston cdesc->control_data.context_hi = SAFEXCEL_ADDR_HI(context); 1956b356ddf0SMark Johnston } 1957b356ddf0SMark Johnston 1958b356ddf0SMark Johnston return (cdesc); 1959b356ddf0SMark Johnston } 1960b356ddf0SMark Johnston 1961b356ddf0SMark Johnston static void 1962b356ddf0SMark Johnston safexcel_cmd_descr_rollback(struct safexcel_ring *ring, int count) 1963b356ddf0SMark Johnston { 1964b356ddf0SMark Johnston struct safexcel_cmd_descr_ring *cring; 1965b356ddf0SMark Johnston 1966b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 1967b356ddf0SMark Johnston 1968b356ddf0SMark Johnston cring = &ring->cdr; 1969b356ddf0SMark Johnston cring->write -= count; 1970b356ddf0SMark Johnston if (cring->write < 0) 1971b356ddf0SMark Johnston cring->write += SAFEXCEL_RING_SIZE; 1972b356ddf0SMark Johnston } 1973b356ddf0SMark Johnston 1974b356ddf0SMark Johnston static void 1975b356ddf0SMark Johnston safexcel_res_descr_rollback(struct safexcel_ring *ring, int count) 1976b356ddf0SMark Johnston { 1977b356ddf0SMark Johnston struct safexcel_res_descr_ring *rring; 1978b356ddf0SMark Johnston 1979b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 1980b356ddf0SMark Johnston 1981b356ddf0SMark Johnston rring = &ring->rdr; 1982b356ddf0SMark Johnston rring->write -= count; 1983b356ddf0SMark Johnston if (rring->write < 0) 1984b356ddf0SMark Johnston rring->write += SAFEXCEL_RING_SIZE; 1985b356ddf0SMark Johnston } 1986b356ddf0SMark Johnston 1987b356ddf0SMark Johnston static void 1988b356ddf0SMark Johnston safexcel_append_segs(bus_dma_segment_t *segs, int nseg, struct sglist *sg, 1989b356ddf0SMark Johnston int start, int len) 1990b356ddf0SMark Johnston { 1991b356ddf0SMark Johnston bus_dma_segment_t *seg; 1992b356ddf0SMark Johnston size_t seglen; 1993b356ddf0SMark Johnston int error, i; 1994b356ddf0SMark Johnston 1995b356ddf0SMark Johnston for (i = 0; i < nseg && len > 0; i++) { 1996b356ddf0SMark Johnston seg = &segs[i]; 1997b356ddf0SMark Johnston 1998b356ddf0SMark Johnston if (seg->ds_len <= start) { 1999b356ddf0SMark Johnston start -= seg->ds_len; 2000b356ddf0SMark Johnston continue; 2001b356ddf0SMark Johnston } 2002b356ddf0SMark Johnston 2003b356ddf0SMark Johnston seglen = MIN(len, seg->ds_len - start); 2004b356ddf0SMark Johnston error = sglist_append_phys(sg, seg->ds_addr + start, seglen); 2005b356ddf0SMark Johnston if (error != 0) 2006b356ddf0SMark Johnston panic("%s: ran out of segments: %d", __func__, error); 2007b356ddf0SMark Johnston len -= seglen; 2008b356ddf0SMark Johnston start = 0; 2009b356ddf0SMark Johnston } 2010b356ddf0SMark Johnston } 2011b356ddf0SMark Johnston 2012b356ddf0SMark Johnston static void 2013b356ddf0SMark Johnston safexcel_create_chain_cb(void *arg, bus_dma_segment_t *segs, int nseg, 2014b356ddf0SMark Johnston int error) 2015b356ddf0SMark Johnston { 2016b356ddf0SMark Johnston const struct crypto_session_params *csp; 2017b356ddf0SMark Johnston struct cryptop *crp; 2018b356ddf0SMark Johnston struct safexcel_cmd_descr *cdesc; 2019b356ddf0SMark Johnston struct safexcel_request *req; 2020b356ddf0SMark Johnston struct safexcel_ring *ring; 2021b356ddf0SMark Johnston struct safexcel_session *sess; 2022b356ddf0SMark Johnston struct sglist *sg; 2023b356ddf0SMark Johnston size_t inlen; 2024b356ddf0SMark Johnston int i; 2025b356ddf0SMark Johnston bool first, last; 2026b356ddf0SMark Johnston 2027b356ddf0SMark Johnston req = arg; 2028b356ddf0SMark Johnston if (error != 0) { 2029b356ddf0SMark Johnston req->error = error; 2030b356ddf0SMark Johnston return; 2031b356ddf0SMark Johnston } 2032b356ddf0SMark Johnston 2033b356ddf0SMark Johnston crp = req->crp; 2034b356ddf0SMark Johnston csp = crypto_get_params(crp->crp_session); 2035b356ddf0SMark Johnston sess = req->sess; 2036e934d455SMark Johnston ring = &req->sc->sc_ring[req->ringidx]; 2037b356ddf0SMark Johnston 2038b356ddf0SMark Johnston mtx_assert(&ring->mtx, MA_OWNED); 2039b356ddf0SMark Johnston 2040b356ddf0SMark Johnston /* 2041b356ddf0SMark Johnston * Set up descriptors for input and output data. 2042b356ddf0SMark Johnston * 2043b356ddf0SMark Johnston * The processing engine programs require that any AAD comes first, 2044b356ddf0SMark Johnston * followed by the cipher plaintext, followed by the digest. Some 2045b356ddf0SMark Johnston * consumers place the digest first in the input buffer, in which case 2046b356ddf0SMark Johnston * we have to create an extra descriptor. 2047b356ddf0SMark Johnston * 2048b356ddf0SMark Johnston * As an optimization, unmodified data is not passed to the output 2049b356ddf0SMark Johnston * stream. 2050b356ddf0SMark Johnston */ 2051b356ddf0SMark Johnston sglist_reset(ring->cmd_data); 2052b356ddf0SMark Johnston sglist_reset(ring->res_data); 2053b356ddf0SMark Johnston if (crp->crp_aad_length != 0) { 2054b356ddf0SMark Johnston safexcel_append_segs(segs, nseg, ring->cmd_data, 2055b356ddf0SMark Johnston crp->crp_aad_start, crp->crp_aad_length); 2056b356ddf0SMark Johnston } 2057b356ddf0SMark Johnston safexcel_append_segs(segs, nseg, ring->cmd_data, 2058b356ddf0SMark Johnston crp->crp_payload_start, crp->crp_payload_length); 2059b356ddf0SMark Johnston if (csp->csp_cipher_alg != 0) { 2060b356ddf0SMark Johnston safexcel_append_segs(segs, nseg, ring->res_data, 2061b356ddf0SMark Johnston crp->crp_payload_start, crp->crp_payload_length); 2062b356ddf0SMark Johnston } 2063b356ddf0SMark Johnston if (sess->digestlen > 0) { 2064b356ddf0SMark Johnston if ((crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) != 0) { 2065b356ddf0SMark Johnston safexcel_append_segs(segs, nseg, ring->cmd_data, 2066b356ddf0SMark Johnston crp->crp_digest_start, sess->digestlen); 2067b356ddf0SMark Johnston } else { 2068b356ddf0SMark Johnston safexcel_append_segs(segs, nseg, ring->res_data, 2069b356ddf0SMark Johnston crp->crp_digest_start, sess->digestlen); 2070b356ddf0SMark Johnston } 2071b356ddf0SMark Johnston } 2072b356ddf0SMark Johnston 2073b356ddf0SMark Johnston sg = ring->cmd_data; 2074b356ddf0SMark Johnston if (sg->sg_nseg == 0) { 2075b356ddf0SMark Johnston /* 2076b356ddf0SMark Johnston * Fake a segment for the command descriptor if the input has 2077b356ddf0SMark Johnston * length zero. The EIP97 apparently does not handle 2078b356ddf0SMark Johnston * zero-length packets properly since subsequent requests return 2079b356ddf0SMark Johnston * bogus errors, so provide a dummy segment using the context 2080b356ddf0SMark Johnston * descriptor. 2081b356ddf0SMark Johnston */ 2082b356ddf0SMark Johnston (void)sglist_append_phys(sg, req->ctx.paddr, 1); 2083b356ddf0SMark Johnston } 2084b356ddf0SMark Johnston for (i = 0, inlen = 0; i < sg->sg_nseg; i++) 2085b356ddf0SMark Johnston inlen += sg->sg_segs[i].ss_len; 2086b356ddf0SMark Johnston for (i = 0; i < sg->sg_nseg; i++) { 2087b356ddf0SMark Johnston first = i == 0; 2088b356ddf0SMark Johnston last = i == sg->sg_nseg - 1; 2089b356ddf0SMark Johnston 2090b356ddf0SMark Johnston cdesc = safexcel_cmd_descr_add(ring, first, last, 2091b356ddf0SMark Johnston sg->sg_segs[i].ss_paddr, sg->sg_segs[i].ss_len, 2092b356ddf0SMark Johnston (uint32_t)inlen, req->ctx.paddr); 2093b356ddf0SMark Johnston if (cdesc == NULL) { 2094b356ddf0SMark Johnston safexcel_cmd_descr_rollback(ring, i); 2095*0371c3faSMark Johnston counter_u64_add(req->sc->sc_cdesc_alloc_failures, 1); 2096b356ddf0SMark Johnston req->error = EAGAIN; 2097b356ddf0SMark Johnston return; 2098b356ddf0SMark Johnston } 2099b356ddf0SMark Johnston if (i == 0) 2100b356ddf0SMark Johnston req->cdesc = cdesc; 2101b356ddf0SMark Johnston } 2102b356ddf0SMark Johnston req->cdescs = sg->sg_nseg; 2103b356ddf0SMark Johnston 2104b356ddf0SMark Johnston sg = ring->res_data; 2105b356ddf0SMark Johnston if (sg->sg_nseg == 0) { 2106b356ddf0SMark Johnston /* 2107b356ddf0SMark Johnston * We need a result descriptor even if the output stream will be 2108b356ddf0SMark Johnston * empty, for example when verifying an AAD digest. 2109b356ddf0SMark Johnston */ 2110b356ddf0SMark Johnston sg->sg_segs[0].ss_paddr = 0; 2111b356ddf0SMark Johnston sg->sg_segs[0].ss_len = 0; 2112b356ddf0SMark Johnston sg->sg_nseg = 1; 2113b356ddf0SMark Johnston } 2114b356ddf0SMark Johnston for (i = 0; i < sg->sg_nseg; i++) { 2115b356ddf0SMark Johnston first = i == 0; 2116b356ddf0SMark Johnston last = i == sg->sg_nseg - 1; 2117b356ddf0SMark Johnston 2118b356ddf0SMark Johnston if (safexcel_res_descr_add(ring, first, last, 2119b356ddf0SMark Johnston sg->sg_segs[i].ss_paddr, sg->sg_segs[i].ss_len) == NULL) { 2120b356ddf0SMark Johnston safexcel_cmd_descr_rollback(ring, 2121b356ddf0SMark Johnston ring->cmd_data->sg_nseg); 2122b356ddf0SMark Johnston safexcel_res_descr_rollback(ring, i); 2123*0371c3faSMark Johnston counter_u64_add(req->sc->sc_rdesc_alloc_failures, 1); 2124b356ddf0SMark Johnston req->error = EAGAIN; 2125b356ddf0SMark Johnston return; 2126b356ddf0SMark Johnston } 2127b356ddf0SMark Johnston } 2128b356ddf0SMark Johnston req->rdescs = sg->sg_nseg; 2129b356ddf0SMark Johnston } 2130b356ddf0SMark Johnston 2131b356ddf0SMark Johnston static int 2132b356ddf0SMark Johnston safexcel_create_chain(struct safexcel_ring *ring, struct safexcel_request *req) 2133b356ddf0SMark Johnston { 2134b356ddf0SMark Johnston int error; 2135b356ddf0SMark Johnston 2136b356ddf0SMark Johnston req->error = 0; 2137b356ddf0SMark Johnston req->cdescs = req->rdescs = 0; 2138b356ddf0SMark Johnston 2139b356ddf0SMark Johnston error = bus_dmamap_load_crp(ring->data_dtag, req->dmap, req->crp, 2140b356ddf0SMark Johnston safexcel_create_chain_cb, req, BUS_DMA_NOWAIT); 2141b356ddf0SMark Johnston if (error == 0) 2142b356ddf0SMark Johnston req->dmap_loaded = true; 2143b356ddf0SMark Johnston 2144b356ddf0SMark Johnston if (req->error != 0) 2145b356ddf0SMark Johnston error = req->error; 2146b356ddf0SMark Johnston 2147b356ddf0SMark Johnston return (error); 2148b356ddf0SMark Johnston } 2149b356ddf0SMark Johnston 2150b356ddf0SMark Johnston static bool 2151b356ddf0SMark Johnston safexcel_probe_cipher(const struct crypto_session_params *csp) 2152b356ddf0SMark Johnston { 2153b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 2154b356ddf0SMark Johnston case CRYPTO_AES_CBC: 2155b356ddf0SMark Johnston case CRYPTO_AES_ICM: 2156b356ddf0SMark Johnston if (csp->csp_ivlen != AES_BLOCK_LEN) 2157b356ddf0SMark Johnston return (false); 2158b356ddf0SMark Johnston break; 2159b356ddf0SMark Johnston case CRYPTO_AES_XTS: 2160b356ddf0SMark Johnston if (csp->csp_ivlen != AES_XTS_IV_LEN) 2161b356ddf0SMark Johnston return (false); 2162b356ddf0SMark Johnston break; 2163b356ddf0SMark Johnston default: 2164b356ddf0SMark Johnston return (false); 2165b356ddf0SMark Johnston } 2166b356ddf0SMark Johnston 2167b356ddf0SMark Johnston return (true); 2168b356ddf0SMark Johnston } 2169b356ddf0SMark Johnston 2170b356ddf0SMark Johnston /* 2171b356ddf0SMark Johnston * Determine whether the driver can implement a session with the requested 2172b356ddf0SMark Johnston * parameters. 2173b356ddf0SMark Johnston */ 2174b356ddf0SMark Johnston static int 2175b356ddf0SMark Johnston safexcel_probesession(device_t dev, const struct crypto_session_params *csp) 2176b356ddf0SMark Johnston { 2177b356ddf0SMark Johnston switch (csp->csp_mode) { 2178b356ddf0SMark Johnston case CSP_MODE_CIPHER: 2179b356ddf0SMark Johnston if (!safexcel_probe_cipher(csp)) 2180b356ddf0SMark Johnston return (EINVAL); 2181b356ddf0SMark Johnston break; 2182b356ddf0SMark Johnston case CSP_MODE_DIGEST: 2183b356ddf0SMark Johnston switch (csp->csp_auth_alg) { 2184b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 2185b356ddf0SMark Johnston if (csp->csp_ivlen != AES_GCM_IV_LEN) 2186b356ddf0SMark Johnston return (EINVAL); 2187b356ddf0SMark Johnston break; 2188b356ddf0SMark Johnston case CRYPTO_SHA1: 2189b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2190b356ddf0SMark Johnston case CRYPTO_SHA2_224: 2191b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2192b356ddf0SMark Johnston case CRYPTO_SHA2_256: 2193b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2194b356ddf0SMark Johnston case CRYPTO_SHA2_384: 2195b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2196b356ddf0SMark Johnston case CRYPTO_SHA2_512: 2197b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2198b356ddf0SMark Johnston break; 2199b356ddf0SMark Johnston default: 2200b356ddf0SMark Johnston return (EINVAL); 2201b356ddf0SMark Johnston } 2202b356ddf0SMark Johnston break; 2203b356ddf0SMark Johnston case CSP_MODE_AEAD: 2204b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 2205b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 2206b356ddf0SMark Johnston if (csp->csp_ivlen != AES_GCM_IV_LEN) 2207b356ddf0SMark Johnston return (EINVAL); 2208b356ddf0SMark Johnston break; 2209b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 2210b356ddf0SMark Johnston if (csp->csp_ivlen != AES_CCM_IV_LEN) 2211b356ddf0SMark Johnston return (EINVAL); 2212b356ddf0SMark Johnston break; 2213b356ddf0SMark Johnston default: 2214b356ddf0SMark Johnston return (EINVAL); 2215b356ddf0SMark Johnston } 2216b356ddf0SMark Johnston break; 2217b356ddf0SMark Johnston case CSP_MODE_ETA: 2218b356ddf0SMark Johnston if (!safexcel_probe_cipher(csp)) 2219b356ddf0SMark Johnston return (EINVAL); 2220b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 2221b356ddf0SMark Johnston case CRYPTO_AES_CBC: 2222b356ddf0SMark Johnston case CRYPTO_AES_ICM: 2223b356ddf0SMark Johnston /* 2224b356ddf0SMark Johnston * The EIP-97 does not support combining AES-XTS with 2225b356ddf0SMark Johnston * hash operations. 2226b356ddf0SMark Johnston */ 2227b356ddf0SMark Johnston if (csp->csp_auth_alg != CRYPTO_SHA1_HMAC && 2228b356ddf0SMark Johnston csp->csp_auth_alg != CRYPTO_SHA2_224_HMAC && 2229b356ddf0SMark Johnston csp->csp_auth_alg != CRYPTO_SHA2_256_HMAC && 2230b356ddf0SMark Johnston csp->csp_auth_alg != CRYPTO_SHA2_384_HMAC && 2231b356ddf0SMark Johnston csp->csp_auth_alg != CRYPTO_SHA2_512_HMAC) 2232b356ddf0SMark Johnston return (EINVAL); 2233b356ddf0SMark Johnston break; 2234b356ddf0SMark Johnston default: 2235b356ddf0SMark Johnston return (EINVAL); 2236b356ddf0SMark Johnston } 2237b356ddf0SMark Johnston break; 2238b356ddf0SMark Johnston default: 2239b356ddf0SMark Johnston return (EINVAL); 2240b356ddf0SMark Johnston } 2241b356ddf0SMark Johnston 2242b356ddf0SMark Johnston return (CRYPTODEV_PROBE_HARDWARE); 2243b356ddf0SMark Johnston } 2244b356ddf0SMark Johnston 2245b356ddf0SMark Johnston /* 2246b356ddf0SMark Johnston * Pre-compute the hash key used in GHASH, which is a block of zeroes encrypted 2247b356ddf0SMark Johnston * using the cipher key. 2248b356ddf0SMark Johnston */ 2249b356ddf0SMark Johnston static void 2250b356ddf0SMark Johnston safexcel_setkey_ghash(struct safexcel_session *sess, const uint8_t *key, 2251b356ddf0SMark Johnston int klen) 2252b356ddf0SMark Johnston { 2253b356ddf0SMark Johnston uint32_t ks[4 * (RIJNDAEL_MAXNR + 1)]; 2254b356ddf0SMark Johnston uint8_t zeros[AES_BLOCK_LEN]; 2255b356ddf0SMark Johnston int i, rounds; 2256b356ddf0SMark Johnston 2257b356ddf0SMark Johnston memset(zeros, 0, sizeof(zeros)); 2258b356ddf0SMark Johnston 2259b356ddf0SMark Johnston rounds = rijndaelKeySetupEnc(ks, key, klen * NBBY); 2260b356ddf0SMark Johnston rijndaelEncrypt(ks, rounds, zeros, (uint8_t *)sess->ghash_key); 2261b356ddf0SMark Johnston for (i = 0; i < GMAC_BLOCK_LEN / sizeof(uint32_t); i++) 2262b356ddf0SMark Johnston sess->ghash_key[i] = htobe32(sess->ghash_key[i]); 2263b356ddf0SMark Johnston 2264b356ddf0SMark Johnston explicit_bzero(ks, sizeof(ks)); 2265b356ddf0SMark Johnston } 2266b356ddf0SMark Johnston 2267b356ddf0SMark Johnston /* 2268b356ddf0SMark Johnston * Pre-compute the combined CBC-MAC key, which consists of three keys K1, K2, K3 2269b356ddf0SMark Johnston * in the hardware implementation. K1 is the cipher key and comes last in the 2270b356ddf0SMark Johnston * buffer since K2 and K3 have a fixed size of AES_BLOCK_LEN. For now XCBC-MAC 2271b356ddf0SMark Johnston * is not implemented so K2 and K3 are fixed. 2272b356ddf0SMark Johnston */ 2273b356ddf0SMark Johnston static void 2274b356ddf0SMark Johnston safexcel_setkey_xcbcmac(struct safexcel_session *sess, const uint8_t *key, 2275b356ddf0SMark Johnston int klen) 2276b356ddf0SMark Johnston { 2277b356ddf0SMark Johnston int i, off; 2278b356ddf0SMark Johnston 2279b356ddf0SMark Johnston memset(sess->xcbc_key, 0, sizeof(sess->xcbc_key)); 2280b356ddf0SMark Johnston off = 2 * AES_BLOCK_LEN / sizeof(uint32_t); 2281b356ddf0SMark Johnston for (i = 0; i < klen / sizeof(uint32_t); i++, key += 4) 2282b356ddf0SMark Johnston sess->xcbc_key[i + off] = htobe32(le32dec(key)); 2283b356ddf0SMark Johnston } 2284b356ddf0SMark Johnston 2285b356ddf0SMark Johnston static void 2286b356ddf0SMark Johnston safexcel_setkey_hmac_digest(struct auth_hash *ahash, union authctx *ctx, 2287b356ddf0SMark Johnston char *buf) 2288b356ddf0SMark Johnston { 2289b356ddf0SMark Johnston int hashwords, i; 2290b356ddf0SMark Johnston 2291b356ddf0SMark Johnston switch (ahash->type) { 2292b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2293b356ddf0SMark Johnston hashwords = ahash->hashsize / sizeof(uint32_t); 2294b356ddf0SMark Johnston for (i = 0; i < hashwords; i++) 2295b356ddf0SMark Johnston ((uint32_t *)buf)[i] = htobe32(ctx->sha1ctx.h.b32[i]); 2296b356ddf0SMark Johnston break; 2297b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2298b356ddf0SMark Johnston hashwords = auth_hash_hmac_sha2_256.hashsize / sizeof(uint32_t); 2299b356ddf0SMark Johnston for (i = 0; i < hashwords; i++) 2300b356ddf0SMark Johnston ((uint32_t *)buf)[i] = htobe32(ctx->sha224ctx.state[i]); 2301b356ddf0SMark Johnston break; 2302b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2303b356ddf0SMark Johnston hashwords = ahash->hashsize / sizeof(uint32_t); 2304b356ddf0SMark Johnston for (i = 0; i < hashwords; i++) 2305b356ddf0SMark Johnston ((uint32_t *)buf)[i] = htobe32(ctx->sha256ctx.state[i]); 2306b356ddf0SMark Johnston break; 2307b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2308b356ddf0SMark Johnston hashwords = auth_hash_hmac_sha2_512.hashsize / sizeof(uint64_t); 2309b356ddf0SMark Johnston for (i = 0; i < hashwords; i++) 2310b356ddf0SMark Johnston ((uint64_t *)buf)[i] = htobe64(ctx->sha384ctx.state[i]); 2311b356ddf0SMark Johnston break; 2312b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2313b356ddf0SMark Johnston hashwords = ahash->hashsize / sizeof(uint64_t); 2314b356ddf0SMark Johnston for (i = 0; i < hashwords; i++) 2315b356ddf0SMark Johnston ((uint64_t *)buf)[i] = htobe64(ctx->sha512ctx.state[i]); 2316b356ddf0SMark Johnston break; 2317b356ddf0SMark Johnston } 2318b356ddf0SMark Johnston } 2319b356ddf0SMark Johnston 2320b356ddf0SMark Johnston /* 2321b356ddf0SMark Johnston * Pre-compute the inner and outer digests used in the HMAC algorithm. 2322b356ddf0SMark Johnston */ 2323b356ddf0SMark Johnston static void 2324b356ddf0SMark Johnston safexcel_setkey_hmac(const struct crypto_session_params *csp, 2325b356ddf0SMark Johnston struct safexcel_session *sess, const uint8_t *key, int klen) 2326b356ddf0SMark Johnston { 2327b356ddf0SMark Johnston union authctx ctx; 2328b356ddf0SMark Johnston struct auth_hash *ahash; 2329b356ddf0SMark Johnston 2330b356ddf0SMark Johnston ahash = crypto_auth_hash(csp); 2331b356ddf0SMark Johnston hmac_init_ipad(ahash, key, klen, &ctx); 2332b356ddf0SMark Johnston safexcel_setkey_hmac_digest(ahash, &ctx, sess->hmac_ipad); 2333b356ddf0SMark Johnston hmac_init_opad(ahash, key, klen, &ctx); 2334b356ddf0SMark Johnston safexcel_setkey_hmac_digest(ahash, &ctx, sess->hmac_opad); 2335b356ddf0SMark Johnston explicit_bzero(&ctx, ahash->ctxsize); 2336b356ddf0SMark Johnston } 2337b356ddf0SMark Johnston 2338b356ddf0SMark Johnston static void 2339b356ddf0SMark Johnston safexcel_setkey_xts(struct safexcel_session *sess, const uint8_t *key, int klen) 2340b356ddf0SMark Johnston { 2341b356ddf0SMark Johnston memcpy(sess->tweak_key, key + klen / 2, klen / 2); 2342b356ddf0SMark Johnston } 2343b356ddf0SMark Johnston 2344b356ddf0SMark Johnston static void 2345b356ddf0SMark Johnston safexcel_setkey(struct safexcel_session *sess, 2346b356ddf0SMark Johnston const struct crypto_session_params *csp, struct cryptop *crp) 2347b356ddf0SMark Johnston { 2348b356ddf0SMark Johnston const uint8_t *akey, *ckey; 2349b356ddf0SMark Johnston int aklen, cklen; 2350b356ddf0SMark Johnston 2351b356ddf0SMark Johnston aklen = csp->csp_auth_klen; 2352b356ddf0SMark Johnston cklen = csp->csp_cipher_klen; 2353b356ddf0SMark Johnston akey = ckey = NULL; 2354b356ddf0SMark Johnston if (crp != NULL) { 2355b356ddf0SMark Johnston akey = crp->crp_auth_key; 2356b356ddf0SMark Johnston ckey = crp->crp_cipher_key; 2357b356ddf0SMark Johnston } 2358b356ddf0SMark Johnston if (akey == NULL) 2359b356ddf0SMark Johnston akey = csp->csp_auth_key; 2360b356ddf0SMark Johnston if (ckey == NULL) 2361b356ddf0SMark Johnston ckey = csp->csp_cipher_key; 2362b356ddf0SMark Johnston 2363b356ddf0SMark Johnston sess->klen = cklen; 2364b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 2365b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 2366b356ddf0SMark Johnston safexcel_setkey_ghash(sess, ckey, cklen); 2367b356ddf0SMark Johnston break; 2368b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 2369b356ddf0SMark Johnston safexcel_setkey_xcbcmac(sess, ckey, cklen); 2370b356ddf0SMark Johnston break; 2371b356ddf0SMark Johnston case CRYPTO_AES_XTS: 2372b356ddf0SMark Johnston safexcel_setkey_xts(sess, ckey, cklen); 2373b356ddf0SMark Johnston sess->klen /= 2; 2374b356ddf0SMark Johnston break; 2375b356ddf0SMark Johnston } 2376b356ddf0SMark Johnston 2377b356ddf0SMark Johnston switch (csp->csp_auth_alg) { 2378b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2379b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2380b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2381b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2382b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2383b356ddf0SMark Johnston safexcel_setkey_hmac(csp, sess, akey, aklen); 2384b356ddf0SMark Johnston break; 2385b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 2386b356ddf0SMark Johnston sess->klen = aklen; 2387b356ddf0SMark Johnston safexcel_setkey_ghash(sess, akey, aklen); 2388b356ddf0SMark Johnston break; 2389b356ddf0SMark Johnston } 2390b356ddf0SMark Johnston } 2391b356ddf0SMark Johnston 2392b356ddf0SMark Johnston static uint32_t 2393b356ddf0SMark Johnston safexcel_aes_algid(int keylen) 2394b356ddf0SMark Johnston { 2395b356ddf0SMark Johnston switch (keylen) { 2396b356ddf0SMark Johnston case 16: 2397b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_CRYPTO_ALG_AES128); 2398b356ddf0SMark Johnston case 24: 2399b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_CRYPTO_ALG_AES192); 2400b356ddf0SMark Johnston case 32: 2401b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_CRYPTO_ALG_AES256); 2402b356ddf0SMark Johnston default: 2403b356ddf0SMark Johnston panic("invalid AES key length %d", keylen); 2404b356ddf0SMark Johnston } 2405b356ddf0SMark Johnston } 2406b356ddf0SMark Johnston 2407b356ddf0SMark Johnston static uint32_t 2408b356ddf0SMark Johnston safexcel_aes_ccm_hashid(int keylen) 2409b356ddf0SMark Johnston { 2410b356ddf0SMark Johnston switch (keylen) { 2411b356ddf0SMark Johnston case 16: 2412b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_XCBC128); 2413b356ddf0SMark Johnston case 24: 2414b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_XCBC192); 2415b356ddf0SMark Johnston case 32: 2416b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_XCBC256); 2417b356ddf0SMark Johnston default: 2418b356ddf0SMark Johnston panic("invalid AES key length %d", keylen); 2419b356ddf0SMark Johnston } 2420b356ddf0SMark Johnston } 2421b356ddf0SMark Johnston 2422b356ddf0SMark Johnston static uint32_t 2423b356ddf0SMark Johnston safexcel_sha_hashid(int alg) 2424b356ddf0SMark Johnston { 2425b356ddf0SMark Johnston switch (alg) { 2426b356ddf0SMark Johnston case CRYPTO_SHA1: 2427b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2428b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_SHA1); 2429b356ddf0SMark Johnston case CRYPTO_SHA2_224: 2430b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2431b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_SHA224); 2432b356ddf0SMark Johnston case CRYPTO_SHA2_256: 2433b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2434b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_SHA256); 2435b356ddf0SMark Johnston case CRYPTO_SHA2_384: 2436b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2437b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_SHA384); 2438b356ddf0SMark Johnston case CRYPTO_SHA2_512: 2439b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2440b356ddf0SMark Johnston return (SAFEXCEL_CONTROL0_HASH_ALG_SHA512); 2441b356ddf0SMark Johnston default: 2442b356ddf0SMark Johnston __assert_unreachable(); 2443b356ddf0SMark Johnston } 2444b356ddf0SMark Johnston } 2445b356ddf0SMark Johnston 2446b356ddf0SMark Johnston static int 2447b356ddf0SMark Johnston safexcel_sha_hashlen(int alg) 2448b356ddf0SMark Johnston { 2449b356ddf0SMark Johnston switch (alg) { 2450b356ddf0SMark Johnston case CRYPTO_SHA1: 2451b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2452b356ddf0SMark Johnston return (SHA1_HASH_LEN); 2453b356ddf0SMark Johnston case CRYPTO_SHA2_224: 2454b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2455b356ddf0SMark Johnston return (SHA2_224_HASH_LEN); 2456b356ddf0SMark Johnston case CRYPTO_SHA2_256: 2457b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2458b356ddf0SMark Johnston return (SHA2_256_HASH_LEN); 2459b356ddf0SMark Johnston case CRYPTO_SHA2_384: 2460b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2461b356ddf0SMark Johnston return (SHA2_384_HASH_LEN); 2462b356ddf0SMark Johnston case CRYPTO_SHA2_512: 2463b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2464b356ddf0SMark Johnston return (SHA2_512_HASH_LEN); 2465b356ddf0SMark Johnston default: 2466b356ddf0SMark Johnston __assert_unreachable(); 2467b356ddf0SMark Johnston } 2468b356ddf0SMark Johnston } 2469b356ddf0SMark Johnston 2470b356ddf0SMark Johnston static int 2471b356ddf0SMark Johnston safexcel_sha_statelen(int alg) 2472b356ddf0SMark Johnston { 2473b356ddf0SMark Johnston switch (alg) { 2474b356ddf0SMark Johnston case CRYPTO_SHA1: 2475b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2476b356ddf0SMark Johnston return (SHA1_HASH_LEN); 2477b356ddf0SMark Johnston case CRYPTO_SHA2_224: 2478b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2479b356ddf0SMark Johnston case CRYPTO_SHA2_256: 2480b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2481b356ddf0SMark Johnston return (SHA2_256_HASH_LEN); 2482b356ddf0SMark Johnston case CRYPTO_SHA2_384: 2483b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2484b356ddf0SMark Johnston case CRYPTO_SHA2_512: 2485b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2486b356ddf0SMark Johnston return (SHA2_512_HASH_LEN); 2487b356ddf0SMark Johnston default: 2488b356ddf0SMark Johnston __assert_unreachable(); 2489b356ddf0SMark Johnston } 2490b356ddf0SMark Johnston } 2491b356ddf0SMark Johnston 2492b356ddf0SMark Johnston static int 2493b356ddf0SMark Johnston safexcel_newsession(device_t dev, crypto_session_t cses, 2494b356ddf0SMark Johnston const struct crypto_session_params *csp) 2495b356ddf0SMark Johnston { 2496b356ddf0SMark Johnston struct safexcel_session *sess; 2497b356ddf0SMark Johnston struct safexcel_softc *sc; 2498b356ddf0SMark Johnston 2499b356ddf0SMark Johnston sc = device_get_softc(dev); 2500b356ddf0SMark Johnston sess = crypto_get_driver_session(cses); 2501b356ddf0SMark Johnston 2502b356ddf0SMark Johnston switch (csp->csp_auth_alg) { 2503b356ddf0SMark Johnston case CRYPTO_SHA1: 2504b356ddf0SMark Johnston case CRYPTO_SHA2_224: 2505b356ddf0SMark Johnston case CRYPTO_SHA2_256: 2506b356ddf0SMark Johnston case CRYPTO_SHA2_384: 2507b356ddf0SMark Johnston case CRYPTO_SHA2_512: 2508b356ddf0SMark Johnston sess->digest = SAFEXCEL_CONTROL0_DIGEST_PRECOMPUTED; 2509b356ddf0SMark Johnston sess->hash = safexcel_sha_hashid(csp->csp_auth_alg); 2510b356ddf0SMark Johnston sess->digestlen = safexcel_sha_hashlen(csp->csp_auth_alg); 2511b356ddf0SMark Johnston sess->statelen = safexcel_sha_statelen(csp->csp_auth_alg); 2512b356ddf0SMark Johnston break; 2513b356ddf0SMark Johnston case CRYPTO_SHA1_HMAC: 2514b356ddf0SMark Johnston case CRYPTO_SHA2_224_HMAC: 2515b356ddf0SMark Johnston case CRYPTO_SHA2_256_HMAC: 2516b356ddf0SMark Johnston case CRYPTO_SHA2_384_HMAC: 2517b356ddf0SMark Johnston case CRYPTO_SHA2_512_HMAC: 2518b356ddf0SMark Johnston sess->digest = SAFEXCEL_CONTROL0_DIGEST_HMAC; 2519b356ddf0SMark Johnston sess->hash = safexcel_sha_hashid(csp->csp_auth_alg); 2520b356ddf0SMark Johnston sess->digestlen = safexcel_sha_hashlen(csp->csp_auth_alg); 2521b356ddf0SMark Johnston sess->statelen = safexcel_sha_statelen(csp->csp_auth_alg); 2522b356ddf0SMark Johnston break; 2523b356ddf0SMark Johnston case CRYPTO_AES_NIST_GMAC: 2524b356ddf0SMark Johnston sess->digest = SAFEXCEL_CONTROL0_DIGEST_GMAC; 2525b356ddf0SMark Johnston sess->digestlen = GMAC_DIGEST_LEN; 2526b356ddf0SMark Johnston sess->hash = SAFEXCEL_CONTROL0_HASH_ALG_GHASH; 2527b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_auth_klen); 2528b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_GCM; 2529b356ddf0SMark Johnston break; 2530b356ddf0SMark Johnston } 2531b356ddf0SMark Johnston 2532b356ddf0SMark Johnston switch (csp->csp_cipher_alg) { 2533b356ddf0SMark Johnston case CRYPTO_AES_NIST_GCM_16: 2534b356ddf0SMark Johnston sess->digest = SAFEXCEL_CONTROL0_DIGEST_GMAC; 2535b356ddf0SMark Johnston sess->digestlen = GMAC_DIGEST_LEN; 2536b356ddf0SMark Johnston sess->hash = SAFEXCEL_CONTROL0_HASH_ALG_GHASH; 2537b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_cipher_klen); 2538b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_GCM; 2539b356ddf0SMark Johnston break; 2540b356ddf0SMark Johnston case CRYPTO_AES_CCM_16: 2541b356ddf0SMark Johnston sess->hash = safexcel_aes_ccm_hashid(csp->csp_cipher_klen); 2542b356ddf0SMark Johnston sess->digest = SAFEXCEL_CONTROL0_DIGEST_CCM; 2543b356ddf0SMark Johnston sess->digestlen = CCM_CBC_MAX_DIGEST_LEN; 2544b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_cipher_klen); 2545b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_CCM; 2546b356ddf0SMark Johnston break; 2547b356ddf0SMark Johnston case CRYPTO_AES_CBC: 2548b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_cipher_klen); 2549b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_CBC; 2550b356ddf0SMark Johnston break; 2551b356ddf0SMark Johnston case CRYPTO_AES_ICM: 2552b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_cipher_klen); 2553b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_CTR; 2554b356ddf0SMark Johnston break; 2555b356ddf0SMark Johnston case CRYPTO_AES_XTS: 2556b356ddf0SMark Johnston sess->alg = safexcel_aes_algid(csp->csp_cipher_klen / 2); 2557b356ddf0SMark Johnston sess->mode = SAFEXCEL_CONTROL1_CRYPTO_MODE_XTS; 2558b356ddf0SMark Johnston break; 2559b356ddf0SMark Johnston } 2560b356ddf0SMark Johnston 2561b356ddf0SMark Johnston if (csp->csp_auth_mlen != 0) 2562b356ddf0SMark Johnston sess->digestlen = csp->csp_auth_mlen; 2563b356ddf0SMark Johnston 2564b356ddf0SMark Johnston safexcel_setkey(sess, csp, NULL); 2565b356ddf0SMark Johnston 2566b356ddf0SMark Johnston return (0); 2567b356ddf0SMark Johnston } 2568b356ddf0SMark Johnston 2569b356ddf0SMark Johnston static int 2570b356ddf0SMark Johnston safexcel_process(device_t dev, struct cryptop *crp, int hint) 2571b356ddf0SMark Johnston { 2572b356ddf0SMark Johnston const struct crypto_session_params *csp; 2573b356ddf0SMark Johnston struct safexcel_request *req; 2574b356ddf0SMark Johnston struct safexcel_ring *ring; 2575b356ddf0SMark Johnston struct safexcel_session *sess; 2576b356ddf0SMark Johnston struct safexcel_softc *sc; 2577b356ddf0SMark Johnston int error; 2578b356ddf0SMark Johnston 2579b356ddf0SMark Johnston sc = device_get_softc(dev); 2580b356ddf0SMark Johnston sess = crypto_get_driver_session(crp->crp_session); 2581b356ddf0SMark Johnston csp = crypto_get_params(crp->crp_session); 2582b356ddf0SMark Johnston 2583b356ddf0SMark Johnston if (__predict_false(crypto_buffer_len(&crp->crp_buf) > 2584b356ddf0SMark Johnston SAFEXCEL_MAX_REQUEST_SIZE)) { 2585b356ddf0SMark Johnston crp->crp_etype = E2BIG; 2586b356ddf0SMark Johnston crypto_done(crp); 2587b356ddf0SMark Johnston return (0); 2588b356ddf0SMark Johnston } 2589b356ddf0SMark Johnston 2590b356ddf0SMark Johnston if (crp->crp_cipher_key != NULL || crp->crp_auth_key != NULL) 2591b356ddf0SMark Johnston safexcel_setkey(sess, csp, crp); 2592b356ddf0SMark Johnston 2593e934d455SMark Johnston ring = &sc->sc_ring[curcpu % sc->sc_config.rings]; 2594b356ddf0SMark Johnston mtx_lock(&ring->mtx); 2595b356ddf0SMark Johnston req = safexcel_alloc_request(sc, ring); 2596b356ddf0SMark Johnston if (__predict_false(req == NULL)) { 2597092cf8d6SMark Johnston ring->blocked = CRYPTO_SYMQ; 2598b356ddf0SMark Johnston mtx_unlock(&ring->mtx); 2599*0371c3faSMark Johnston counter_u64_add(sc->sc_req_alloc_failures, 1); 2600b356ddf0SMark Johnston return (ERESTART); 2601b356ddf0SMark Johnston } 2602b356ddf0SMark Johnston 2603b356ddf0SMark Johnston req->crp = crp; 2604b356ddf0SMark Johnston req->sess = sess; 2605b356ddf0SMark Johnston 2606b356ddf0SMark Johnston crypto_read_iv(crp, req->iv); 2607b356ddf0SMark Johnston 2608b356ddf0SMark Johnston error = safexcel_create_chain(ring, req); 2609b356ddf0SMark Johnston if (__predict_false(error != 0)) { 2610b356ddf0SMark Johnston safexcel_free_request(ring, req); 2611b356ddf0SMark Johnston mtx_unlock(&ring->mtx); 2612b356ddf0SMark Johnston crp->crp_etype = error; 2613b356ddf0SMark Johnston crypto_done(crp); 2614b356ddf0SMark Johnston return (0); 2615b356ddf0SMark Johnston } 2616b356ddf0SMark Johnston 2617b356ddf0SMark Johnston safexcel_set_token(req); 2618b356ddf0SMark Johnston 2619b356ddf0SMark Johnston bus_dmamap_sync(ring->data_dtag, req->dmap, 2620b356ddf0SMark Johnston BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2621b356ddf0SMark Johnston bus_dmamap_sync(req->ctx.tag, req->ctx.map, 2622b356ddf0SMark Johnston BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2623b356ddf0SMark Johnston bus_dmamap_sync(ring->cdr.dma.tag, ring->cdr.dma.map, 2624b356ddf0SMark Johnston BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2625b356ddf0SMark Johnston bus_dmamap_sync(ring->dma_atok.tag, ring->dma_atok.map, 2626b356ddf0SMark Johnston BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2627b356ddf0SMark Johnston bus_dmamap_sync(ring->rdr.dma.tag, ring->rdr.dma.map, 2628b356ddf0SMark Johnston BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2629b356ddf0SMark Johnston 2630b356ddf0SMark Johnston safexcel_enqueue_request(sc, ring, req); 2631b356ddf0SMark Johnston 2632b356ddf0SMark Johnston if ((hint & CRYPTO_HINT_MORE) == 0) 2633b356ddf0SMark Johnston safexcel_execute(sc, ring, req); 2634b356ddf0SMark Johnston mtx_unlock(&ring->mtx); 2635b356ddf0SMark Johnston 2636b356ddf0SMark Johnston return (0); 2637b356ddf0SMark Johnston } 2638b356ddf0SMark Johnston 2639b356ddf0SMark Johnston static device_method_t safexcel_methods[] = { 2640b356ddf0SMark Johnston /* Device interface */ 2641b356ddf0SMark Johnston DEVMETHOD(device_probe, safexcel_probe), 2642b356ddf0SMark Johnston DEVMETHOD(device_attach, safexcel_attach), 2643b356ddf0SMark Johnston DEVMETHOD(device_detach, safexcel_detach), 2644b356ddf0SMark Johnston 2645b356ddf0SMark Johnston /* Cryptodev interface */ 2646b356ddf0SMark Johnston DEVMETHOD(cryptodev_probesession, safexcel_probesession), 2647b356ddf0SMark Johnston DEVMETHOD(cryptodev_newsession, safexcel_newsession), 2648b356ddf0SMark Johnston DEVMETHOD(cryptodev_process, safexcel_process), 2649b356ddf0SMark Johnston 2650b356ddf0SMark Johnston DEVMETHOD_END 2651b356ddf0SMark Johnston }; 2652b356ddf0SMark Johnston 2653b356ddf0SMark Johnston static devclass_t safexcel_devclass; 2654b356ddf0SMark Johnston 2655b356ddf0SMark Johnston static driver_t safexcel_driver = { 2656b356ddf0SMark Johnston .name = "safexcel", 2657b356ddf0SMark Johnston .methods = safexcel_methods, 2658b356ddf0SMark Johnston .size = sizeof(struct safexcel_softc), 2659b356ddf0SMark Johnston }; 2660b356ddf0SMark Johnston 2661b356ddf0SMark Johnston DRIVER_MODULE(safexcel, simplebus, safexcel_driver, safexcel_devclass, 0, 0); 2662b356ddf0SMark Johnston MODULE_VERSION(safexcel, 1); 2663b356ddf0SMark Johnston MODULE_DEPEND(safexcel, crypto, 1, 1, 1); 2664