102b553caSRafal Jaworowski /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 402b553caSRafal Jaworowski * Copyright (C) 2008-2009 Semihalf, Piotr Ziecik 502b553caSRafal Jaworowski * All rights reserved. 602b553caSRafal Jaworowski * 702b553caSRafal Jaworowski * Redistribution and use in source and binary forms, with or without 802b553caSRafal Jaworowski * modification, are permitted provided that the following conditions 902b553caSRafal Jaworowski * are met: 1002b553caSRafal Jaworowski * 1. Redistributions of source code must retain the above copyright 1102b553caSRafal Jaworowski * notice, this list of conditions and the following disclaimer. 1202b553caSRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright 1302b553caSRafal Jaworowski * notice, this list of conditions and the following disclaimer in the 1402b553caSRafal Jaworowski * documentation and/or other materials provided with the distribution. 1502b553caSRafal Jaworowski * 1602b553caSRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1702b553caSRafal Jaworowski * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1802b553caSRafal Jaworowski * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 1902b553caSRafal Jaworowski * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2002b553caSRafal Jaworowski * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2102b553caSRafal Jaworowski * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2202b553caSRafal Jaworowski * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2302b553caSRafal Jaworowski * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2402b553caSRafal Jaworowski * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2502b553caSRafal Jaworowski * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2602b553caSRafal Jaworowski */ 2702b553caSRafal Jaworowski 2802b553caSRafal Jaworowski /* 2902b553caSRafal Jaworowski * Freescale integrated Security Engine (SEC) driver. Currently SEC 2.0 and 3002b553caSRafal Jaworowski * 3.0 are supported. 3102b553caSRafal Jaworowski */ 3202b553caSRafal Jaworowski 3302b553caSRafal Jaworowski #include <sys/cdefs.h> 3402b553caSRafal Jaworowski __FBSDID("$FreeBSD$"); 3502b553caSRafal Jaworowski 3602b553caSRafal Jaworowski #include <sys/param.h> 3702b553caSRafal Jaworowski #include <sys/systm.h> 3802b553caSRafal Jaworowski #include <sys/bus.h> 3902b553caSRafal Jaworowski #include <sys/endian.h> 4002b553caSRafal Jaworowski #include <sys/kernel.h> 4102b553caSRafal Jaworowski #include <sys/lock.h> 4202b553caSRafal Jaworowski #include <sys/malloc.h> 4302b553caSRafal Jaworowski #include <sys/mbuf.h> 4402b553caSRafal Jaworowski #include <sys/module.h> 4502b553caSRafal Jaworowski #include <sys/mutex.h> 4602b553caSRafal Jaworowski #include <sys/random.h> 4702b553caSRafal Jaworowski #include <sys/rman.h> 4802b553caSRafal Jaworowski 4938f004fbSJustin Hibbits #include <machine/_inttypes.h> 5002b553caSRafal Jaworowski #include <machine/bus.h> 5102b553caSRafal Jaworowski #include <machine/resource.h> 5202b553caSRafal Jaworowski 5302b553caSRafal Jaworowski #include <opencrypto/cryptodev.h> 54c0341432SJohn Baldwin #include <opencrypto/xform_auth.h> 5502b553caSRafal Jaworowski #include "cryptodev_if.h" 5602b553caSRafal Jaworowski 57d1d3233eSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h> 5802b553caSRafal Jaworowski #include <dev/sec/sec.h> 5902b553caSRafal Jaworowski 6002b553caSRafal Jaworowski static int sec_probe(device_t dev); 6102b553caSRafal Jaworowski static int sec_attach(device_t dev); 6202b553caSRafal Jaworowski static int sec_detach(device_t dev); 6302b553caSRafal Jaworowski static int sec_suspend(device_t dev); 6402b553caSRafal Jaworowski static int sec_resume(device_t dev); 65661ee6eeSRafal Jaworowski static int sec_shutdown(device_t dev); 6602b553caSRafal Jaworowski static void sec_primary_intr(void *arg); 6702b553caSRafal Jaworowski static void sec_secondary_intr(void *arg); 6802b553caSRafal Jaworowski static int sec_setup_intr(struct sec_softc *sc, struct resource **ires, 6902b553caSRafal Jaworowski void **ihand, int *irid, driver_intr_t handler, const char *iname); 7002b553caSRafal Jaworowski static void sec_release_intr(struct sec_softc *sc, struct resource *ires, 7102b553caSRafal Jaworowski void *ihand, int irid, const char *iname); 7202b553caSRafal Jaworowski static int sec_controller_reset(struct sec_softc *sc); 7302b553caSRafal Jaworowski static int sec_channel_reset(struct sec_softc *sc, int channel, int full); 7402b553caSRafal Jaworowski static int sec_init(struct sec_softc *sc); 7502b553caSRafal Jaworowski static int sec_alloc_dma_mem(struct sec_softc *sc, 7602b553caSRafal Jaworowski struct sec_dma_mem *dma_mem, bus_size_t size); 7702b553caSRafal Jaworowski static int sec_desc_map_dma(struct sec_softc *sc, 78c0341432SJohn Baldwin struct sec_dma_mem *dma_mem, struct cryptop *crp, bus_size_t size, 7902b553caSRafal Jaworowski struct sec_desc_map_info *sdmi); 8002b553caSRafal Jaworowski static void sec_free_dma_mem(struct sec_dma_mem *dma_mem); 8102b553caSRafal Jaworowski static void sec_enqueue(struct sec_softc *sc); 8202b553caSRafal Jaworowski static int sec_enqueue_desc(struct sec_softc *sc, struct sec_desc *desc, 8302b553caSRafal Jaworowski int channel); 8402b553caSRafal Jaworowski static int sec_eu_channel(struct sec_softc *sc, int eu); 8502b553caSRafal Jaworowski static int sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, 86c0341432SJohn Baldwin u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize); 8702b553caSRafal Jaworowski static int sec_make_pointer_direct(struct sec_softc *sc, 8802b553caSRafal Jaworowski struct sec_desc *desc, u_int n, bus_addr_t data, bus_size_t dsize); 89c0341432SJohn Baldwin static int sec_probesession(device_t dev, 90c0341432SJohn Baldwin const struct crypto_session_params *csp); 911b0909d5SConrad Meyer static int sec_newsession(device_t dev, crypto_session_t cses, 92c0341432SJohn Baldwin const struct crypto_session_params *csp); 9302b553caSRafal Jaworowski static int sec_process(device_t dev, struct cryptop *crp, int hint); 9402b553caSRafal Jaworowski static int sec_build_common_ns_desc(struct sec_softc *sc, 95c0341432SJohn Baldwin struct sec_desc *desc, const struct crypto_session_params *csp, 96c0341432SJohn Baldwin struct cryptop *crp); 9702b553caSRafal Jaworowski static int sec_build_common_s_desc(struct sec_softc *sc, 98c0341432SJohn Baldwin struct sec_desc *desc, const struct crypto_session_params *csp, 99c0341432SJohn Baldwin struct cryptop *crp); 10002b553caSRafal Jaworowski 10102b553caSRafal Jaworowski static struct sec_desc *sec_find_desc(struct sec_softc *sc, bus_addr_t paddr); 10202b553caSRafal Jaworowski 10302b553caSRafal Jaworowski /* AESU */ 104c0341432SJohn Baldwin static bool sec_aesu_newsession(const struct crypto_session_params *csp); 10502b553caSRafal Jaworowski static int sec_aesu_make_desc(struct sec_softc *sc, 106c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc, 107c0341432SJohn Baldwin struct cryptop *crp); 10802b553caSRafal Jaworowski 10902b553caSRafal Jaworowski /* MDEU */ 110c0341432SJohn Baldwin static bool sec_mdeu_can_handle(u_int alg); 111c0341432SJohn Baldwin static int sec_mdeu_config(const struct crypto_session_params *csp, 11202b553caSRafal Jaworowski u_int *eu, u_int *mode, u_int *hashlen); 113c0341432SJohn Baldwin static bool sec_mdeu_newsession(const struct crypto_session_params *csp); 11402b553caSRafal Jaworowski static int sec_mdeu_make_desc(struct sec_softc *sc, 115c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc, 116c0341432SJohn Baldwin struct cryptop *crp); 11702b553caSRafal Jaworowski 11802b553caSRafal Jaworowski static device_method_t sec_methods[] = { 11902b553caSRafal Jaworowski /* Device interface */ 12002b553caSRafal Jaworowski DEVMETHOD(device_probe, sec_probe), 12102b553caSRafal Jaworowski DEVMETHOD(device_attach, sec_attach), 12202b553caSRafal Jaworowski DEVMETHOD(device_detach, sec_detach), 12302b553caSRafal Jaworowski 12402b553caSRafal Jaworowski DEVMETHOD(device_suspend, sec_suspend), 12502b553caSRafal Jaworowski DEVMETHOD(device_resume, sec_resume), 12602b553caSRafal Jaworowski DEVMETHOD(device_shutdown, sec_shutdown), 12702b553caSRafal Jaworowski 12802b553caSRafal Jaworowski /* Crypto methods */ 129c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, sec_probesession), 13002b553caSRafal Jaworowski DEVMETHOD(cryptodev_newsession, sec_newsession), 13102b553caSRafal Jaworowski DEVMETHOD(cryptodev_process, sec_process), 13202b553caSRafal Jaworowski 1334b7ec270SMarius Strobl DEVMETHOD_END 13402b553caSRafal Jaworowski }; 13502b553caSRafal Jaworowski static driver_t sec_driver = { 13602b553caSRafal Jaworowski "sec", 13702b553caSRafal Jaworowski sec_methods, 13802b553caSRafal Jaworowski sizeof(struct sec_softc), 13902b553caSRafal Jaworowski }; 14002b553caSRafal Jaworowski 14102b553caSRafal Jaworowski static devclass_t sec_devclass; 142d1d3233eSRafal Jaworowski DRIVER_MODULE(sec, simplebus, sec_driver, sec_devclass, 0, 0); 14302b553caSRafal Jaworowski MODULE_DEPEND(sec, crypto, 1, 1, 1); 14402b553caSRafal Jaworowski 14502b553caSRafal Jaworowski static struct sec_eu_methods sec_eus[] = { 14602b553caSRafal Jaworowski { 14702b553caSRafal Jaworowski sec_aesu_newsession, 14802b553caSRafal Jaworowski sec_aesu_make_desc, 14902b553caSRafal Jaworowski }, 15002b553caSRafal Jaworowski { 15102b553caSRafal Jaworowski sec_mdeu_newsession, 15202b553caSRafal Jaworowski sec_mdeu_make_desc, 15302b553caSRafal Jaworowski }, 15402b553caSRafal Jaworowski { NULL, NULL } 15502b553caSRafal Jaworowski }; 15602b553caSRafal Jaworowski 15702b553caSRafal Jaworowski static inline void 15802b553caSRafal Jaworowski sec_sync_dma_mem(struct sec_dma_mem *dma_mem, bus_dmasync_op_t op) 15902b553caSRafal Jaworowski { 16002b553caSRafal Jaworowski 16102b553caSRafal Jaworowski /* Sync only if dma memory is valid */ 16202b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL) 16302b553caSRafal Jaworowski bus_dmamap_sync(dma_mem->dma_tag, dma_mem->dma_map, op); 16402b553caSRafal Jaworowski } 16502b553caSRafal Jaworowski 16602b553caSRafal Jaworowski static inline void * 16702b553caSRafal Jaworowski sec_get_pointer_data(struct sec_desc *desc, u_int n) 16802b553caSRafal Jaworowski { 16902b553caSRafal Jaworowski 17002b553caSRafal Jaworowski return (desc->sd_ptr_dmem[n].dma_vaddr); 17102b553caSRafal Jaworowski } 17202b553caSRafal Jaworowski 17302b553caSRafal Jaworowski static int 17402b553caSRafal Jaworowski sec_probe(device_t dev) 17502b553caSRafal Jaworowski { 17602b553caSRafal Jaworowski struct sec_softc *sc; 17702b553caSRafal Jaworowski uint64_t id; 17802b553caSRafal Jaworowski 179add35ed5SIan Lepore if (!ofw_bus_status_okay(dev)) 180add35ed5SIan Lepore return (ENXIO); 181add35ed5SIan Lepore 182d1d3233eSRafal Jaworowski if (!ofw_bus_is_compatible(dev, "fsl,sec2.0")) 18302b553caSRafal Jaworowski return (ENXIO); 18402b553caSRafal Jaworowski 18502b553caSRafal Jaworowski sc = device_get_softc(dev); 18602b553caSRafal Jaworowski 18702b553caSRafal Jaworowski sc->sc_rrid = 0; 188d1d3233eSRafal Jaworowski sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, 189d1d3233eSRafal Jaworowski RF_ACTIVE); 19002b553caSRafal Jaworowski 19102b553caSRafal Jaworowski if (sc->sc_rres == NULL) 19202b553caSRafal Jaworowski return (ENXIO); 19302b553caSRafal Jaworowski 19402b553caSRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 19502b553caSRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 19602b553caSRafal Jaworowski 19702b553caSRafal Jaworowski id = SEC_READ(sc, SEC_ID); 19802b553caSRafal Jaworowski 19902b553caSRafal Jaworowski bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); 20002b553caSRafal Jaworowski 20102b553caSRafal Jaworowski switch (id) { 20202b553caSRafal Jaworowski case SEC_20_ID: 20302b553caSRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 2.0"); 20402b553caSRafal Jaworowski sc->sc_version = 2; 20502b553caSRafal Jaworowski break; 20602b553caSRafal Jaworowski case SEC_30_ID: 20702b553caSRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 3.0"); 20802b553caSRafal Jaworowski sc->sc_version = 3; 20902b553caSRafal Jaworowski break; 2101aba5158SRafal Jaworowski case SEC_31_ID: 2111aba5158SRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 3.1"); 2121aba5158SRafal Jaworowski sc->sc_version = 3; 2131aba5158SRafal Jaworowski break; 21402b553caSRafal Jaworowski default: 2152afca094SJustin Hibbits device_printf(dev, "unknown SEC ID 0x%016"PRIx64"!\n", id); 21602b553caSRafal Jaworowski return (ENXIO); 21702b553caSRafal Jaworowski } 21802b553caSRafal Jaworowski 21902b553caSRafal Jaworowski return (0); 22002b553caSRafal Jaworowski } 22102b553caSRafal Jaworowski 22202b553caSRafal Jaworowski static int 22302b553caSRafal Jaworowski sec_attach(device_t dev) 22402b553caSRafal Jaworowski { 22502b553caSRafal Jaworowski struct sec_softc *sc; 22602b553caSRafal Jaworowski struct sec_hw_lt *lt; 22702b553caSRafal Jaworowski int error = 0; 22802b553caSRafal Jaworowski int i; 22902b553caSRafal Jaworowski 23002b553caSRafal Jaworowski sc = device_get_softc(dev); 23102b553caSRafal Jaworowski sc->sc_dev = dev; 23202b553caSRafal Jaworowski sc->sc_blocked = 0; 23302b553caSRafal Jaworowski sc->sc_shutdown = 0; 23402b553caSRafal Jaworowski 2351b0909d5SConrad Meyer sc->sc_cid = crypto_get_driverid(dev, sizeof(struct sec_session), 2361b0909d5SConrad Meyer CRYPTOCAP_F_HARDWARE); 23702b553caSRafal Jaworowski if (sc->sc_cid < 0) { 23802b553caSRafal Jaworowski device_printf(dev, "could not get crypto driver ID!\n"); 23902b553caSRafal Jaworowski return (ENXIO); 24002b553caSRafal Jaworowski } 24102b553caSRafal Jaworowski 24202b553caSRafal Jaworowski /* Init locks */ 24302b553caSRafal Jaworowski mtx_init(&sc->sc_controller_lock, device_get_nameunit(dev), 24402b553caSRafal Jaworowski "SEC Controller lock", MTX_DEF); 24502b553caSRafal Jaworowski mtx_init(&sc->sc_descriptors_lock, device_get_nameunit(dev), 24602b553caSRafal Jaworowski "SEC Descriptors lock", MTX_DEF); 24702b553caSRafal Jaworowski 24802b553caSRafal Jaworowski /* Allocate I/O memory for SEC registers */ 24902b553caSRafal Jaworowski sc->sc_rrid = 0; 250d1d3233eSRafal Jaworowski sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, 251d1d3233eSRafal Jaworowski RF_ACTIVE); 25202b553caSRafal Jaworowski 25302b553caSRafal Jaworowski if (sc->sc_rres == NULL) { 25402b553caSRafal Jaworowski device_printf(dev, "could not allocate I/O memory!\n"); 25502b553caSRafal Jaworowski goto fail1; 25602b553caSRafal Jaworowski } 25702b553caSRafal Jaworowski 25802b553caSRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 25902b553caSRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 26002b553caSRafal Jaworowski 26102b553caSRafal Jaworowski /* Setup interrupts */ 26202b553caSRafal Jaworowski sc->sc_pri_irid = 0; 26302b553caSRafal Jaworowski error = sec_setup_intr(sc, &sc->sc_pri_ires, &sc->sc_pri_ihand, 26402b553caSRafal Jaworowski &sc->sc_pri_irid, sec_primary_intr, "primary"); 26502b553caSRafal Jaworowski 26602b553caSRafal Jaworowski if (error) 26702b553caSRafal Jaworowski goto fail2; 26802b553caSRafal Jaworowski 269d1d3233eSRafal Jaworowski if (sc->sc_version == 3) { 27002b553caSRafal Jaworowski sc->sc_sec_irid = 1; 27102b553caSRafal Jaworowski error = sec_setup_intr(sc, &sc->sc_sec_ires, &sc->sc_sec_ihand, 27202b553caSRafal Jaworowski &sc->sc_sec_irid, sec_secondary_intr, "secondary"); 27302b553caSRafal Jaworowski 27402b553caSRafal Jaworowski if (error) 27502b553caSRafal Jaworowski goto fail3; 276d1d3233eSRafal Jaworowski } 27702b553caSRafal Jaworowski 27802b553caSRafal Jaworowski /* Alloc DMA memory for descriptors and link tables */ 27902b553caSRafal Jaworowski error = sec_alloc_dma_mem(sc, &(sc->sc_desc_dmem), 28002b553caSRafal Jaworowski SEC_DESCRIPTORS * sizeof(struct sec_hw_desc)); 28102b553caSRafal Jaworowski 28202b553caSRafal Jaworowski if (error) 28302b553caSRafal Jaworowski goto fail4; 28402b553caSRafal Jaworowski 28502b553caSRafal Jaworowski error = sec_alloc_dma_mem(sc, &(sc->sc_lt_dmem), 28602b553caSRafal Jaworowski (SEC_LT_ENTRIES + 1) * sizeof(struct sec_hw_lt)); 28702b553caSRafal Jaworowski 28802b553caSRafal Jaworowski if (error) 28902b553caSRafal Jaworowski goto fail5; 29002b553caSRafal Jaworowski 29102b553caSRafal Jaworowski /* Fill in descriptors and link tables */ 29202b553caSRafal Jaworowski for (i = 0; i < SEC_DESCRIPTORS; i++) { 29302b553caSRafal Jaworowski sc->sc_desc[i].sd_desc = 29402b553caSRafal Jaworowski (struct sec_hw_desc*)(sc->sc_desc_dmem.dma_vaddr) + i; 29502b553caSRafal Jaworowski sc->sc_desc[i].sd_desc_paddr = sc->sc_desc_dmem.dma_paddr + 29602b553caSRafal Jaworowski (i * sizeof(struct sec_hw_desc)); 29702b553caSRafal Jaworowski } 29802b553caSRafal Jaworowski 29902b553caSRafal Jaworowski for (i = 0; i < SEC_LT_ENTRIES + 1; i++) { 30002b553caSRafal Jaworowski sc->sc_lt[i].sl_lt = 30102b553caSRafal Jaworowski (struct sec_hw_lt*)(sc->sc_lt_dmem.dma_vaddr) + i; 30202b553caSRafal Jaworowski sc->sc_lt[i].sl_lt_paddr = sc->sc_lt_dmem.dma_paddr + 30302b553caSRafal Jaworowski (i * sizeof(struct sec_hw_lt)); 30402b553caSRafal Jaworowski } 30502b553caSRafal Jaworowski 30602b553caSRafal Jaworowski /* Last entry in link table is used to create a circle */ 30702b553caSRafal Jaworowski lt = sc->sc_lt[SEC_LT_ENTRIES].sl_lt; 30802b553caSRafal Jaworowski lt->shl_length = 0; 30902b553caSRafal Jaworowski lt->shl_r = 0; 31002b553caSRafal Jaworowski lt->shl_n = 1; 31102b553caSRafal Jaworowski lt->shl_ptr = sc->sc_lt[0].sl_lt_paddr; 31202b553caSRafal Jaworowski 31302b553caSRafal Jaworowski /* Init descriptor and link table queues pointers */ 31402b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_free_desc_get_cnt, SEC_DESCRIPTORS); 31502b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_free_desc_put_cnt, SEC_DESCRIPTORS); 31602b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_ready_desc_get_cnt, SEC_DESCRIPTORS); 31702b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_ready_desc_put_cnt, SEC_DESCRIPTORS); 31802b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_queued_desc_get_cnt, SEC_DESCRIPTORS); 31902b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_queued_desc_put_cnt, SEC_DESCRIPTORS); 32002b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_lt_alloc_cnt, SEC_LT_ENTRIES); 32102b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_lt_free_cnt, SEC_LT_ENTRIES); 32202b553caSRafal Jaworowski 32302b553caSRafal Jaworowski /* Create masks for fast checks */ 32402b553caSRafal Jaworowski sc->sc_int_error_mask = 0; 32502b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) 32602b553caSRafal Jaworowski sc->sc_int_error_mask |= (~0ULL & SEC_INT_CH_ERR(i)); 32702b553caSRafal Jaworowski 32802b553caSRafal Jaworowski switch (sc->sc_version) { 32902b553caSRafal Jaworowski case 2: 33002b553caSRafal Jaworowski sc->sc_channel_idle_mask = 33102b553caSRafal Jaworowski (SEC_CHAN_CSR2_FFLVL_M << SEC_CHAN_CSR2_FFLVL_S) | 33202b553caSRafal Jaworowski (SEC_CHAN_CSR2_MSTATE_M << SEC_CHAN_CSR2_MSTATE_S) | 33302b553caSRafal Jaworowski (SEC_CHAN_CSR2_PSTATE_M << SEC_CHAN_CSR2_PSTATE_S) | 33402b553caSRafal Jaworowski (SEC_CHAN_CSR2_GSTATE_M << SEC_CHAN_CSR2_GSTATE_S); 33502b553caSRafal Jaworowski break; 33602b553caSRafal Jaworowski case 3: 33702b553caSRafal Jaworowski sc->sc_channel_idle_mask = 33802b553caSRafal Jaworowski (SEC_CHAN_CSR3_FFLVL_M << SEC_CHAN_CSR3_FFLVL_S) | 33902b553caSRafal Jaworowski (SEC_CHAN_CSR3_MSTATE_M << SEC_CHAN_CSR3_MSTATE_S) | 34002b553caSRafal Jaworowski (SEC_CHAN_CSR3_PSTATE_M << SEC_CHAN_CSR3_PSTATE_S) | 34102b553caSRafal Jaworowski (SEC_CHAN_CSR3_GSTATE_M << SEC_CHAN_CSR3_GSTATE_S); 34202b553caSRafal Jaworowski break; 34302b553caSRafal Jaworowski } 34402b553caSRafal Jaworowski 34502b553caSRafal Jaworowski /* Init hardware */ 34602b553caSRafal Jaworowski error = sec_init(sc); 34702b553caSRafal Jaworowski 34802b553caSRafal Jaworowski if (error) 34902b553caSRafal Jaworowski goto fail6; 35002b553caSRafal Jaworowski 35102b553caSRafal Jaworowski return (0); 35202b553caSRafal Jaworowski 35302b553caSRafal Jaworowski fail6: 35402b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_lt_dmem)); 35502b553caSRafal Jaworowski fail5: 35602b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_desc_dmem)); 35702b553caSRafal Jaworowski fail4: 35802b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_sec_ires, sc->sc_sec_ihand, 35902b553caSRafal Jaworowski sc->sc_sec_irid, "secondary"); 36002b553caSRafal Jaworowski fail3: 36102b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_pri_ires, sc->sc_pri_ihand, 36202b553caSRafal Jaworowski sc->sc_pri_irid, "primary"); 36302b553caSRafal Jaworowski fail2: 36402b553caSRafal Jaworowski bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); 36502b553caSRafal Jaworowski fail1: 36602b553caSRafal Jaworowski mtx_destroy(&sc->sc_controller_lock); 36702b553caSRafal Jaworowski mtx_destroy(&sc->sc_descriptors_lock); 36802b553caSRafal Jaworowski 36902b553caSRafal Jaworowski return (ENXIO); 37002b553caSRafal Jaworowski } 37102b553caSRafal Jaworowski 37202b553caSRafal Jaworowski static int 37302b553caSRafal Jaworowski sec_detach(device_t dev) 37402b553caSRafal Jaworowski { 37502b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev); 37602b553caSRafal Jaworowski int i, error, timeout = SEC_TIMEOUT; 37702b553caSRafal Jaworowski 37802b553caSRafal Jaworowski /* Prepare driver to shutdown */ 37902b553caSRafal Jaworowski SEC_LOCK(sc, descriptors); 38002b553caSRafal Jaworowski sc->sc_shutdown = 1; 38102b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 38202b553caSRafal Jaworowski 38302b553caSRafal Jaworowski /* Wait until all queued processing finishes */ 38402b553caSRafal Jaworowski while (1) { 38502b553caSRafal Jaworowski SEC_LOCK(sc, descriptors); 38602b553caSRafal Jaworowski i = SEC_READY_DESC_CNT(sc) + SEC_QUEUED_DESC_CNT(sc); 38702b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 38802b553caSRafal Jaworowski 38902b553caSRafal Jaworowski if (i == 0) 39002b553caSRafal Jaworowski break; 39102b553caSRafal Jaworowski 39202b553caSRafal Jaworowski if (timeout < 0) { 39302b553caSRafal Jaworowski device_printf(dev, "queue flush timeout!\n"); 39402b553caSRafal Jaworowski 39502b553caSRafal Jaworowski /* DMA can be still active - stop it */ 39602b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) 39702b553caSRafal Jaworowski sec_channel_reset(sc, i, 1); 39802b553caSRafal Jaworowski 39902b553caSRafal Jaworowski break; 40002b553caSRafal Jaworowski } 40102b553caSRafal Jaworowski 40202b553caSRafal Jaworowski timeout -= 1000; 40302b553caSRafal Jaworowski DELAY(1000); 40402b553caSRafal Jaworowski } 40502b553caSRafal Jaworowski 40602b553caSRafal Jaworowski /* Disable interrupts */ 40702b553caSRafal Jaworowski SEC_WRITE(sc, SEC_IER, 0); 40802b553caSRafal Jaworowski 40902b553caSRafal Jaworowski /* Unregister from OCF */ 41002b553caSRafal Jaworowski crypto_unregister_all(sc->sc_cid); 41102b553caSRafal Jaworowski 41202b553caSRafal Jaworowski /* Free DMA memory */ 41302b553caSRafal Jaworowski for (i = 0; i < SEC_DESCRIPTORS; i++) 41402b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(&(sc->sc_desc[i])); 41502b553caSRafal Jaworowski 41602b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_lt_dmem)); 41702b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_desc_dmem)); 41802b553caSRafal Jaworowski 41902b553caSRafal Jaworowski /* Release interrupts */ 42002b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_pri_ires, sc->sc_pri_ihand, 42102b553caSRafal Jaworowski sc->sc_pri_irid, "primary"); 42202b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_sec_ires, sc->sc_sec_ihand, 42302b553caSRafal Jaworowski sc->sc_sec_irid, "secondary"); 42402b553caSRafal Jaworowski 42502b553caSRafal Jaworowski /* Release memory */ 42602b553caSRafal Jaworowski if (sc->sc_rres) { 42702b553caSRafal Jaworowski error = bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, 42802b553caSRafal Jaworowski sc->sc_rres); 42902b553caSRafal Jaworowski if (error) 43002b553caSRafal Jaworowski device_printf(dev, "bus_release_resource() failed for" 43102b553caSRafal Jaworowski " I/O memory, error %d\n", error); 43202b553caSRafal Jaworowski 43302b553caSRafal Jaworowski sc->sc_rres = NULL; 43402b553caSRafal Jaworowski } 43502b553caSRafal Jaworowski 43602b553caSRafal Jaworowski mtx_destroy(&sc->sc_controller_lock); 43702b553caSRafal Jaworowski mtx_destroy(&sc->sc_descriptors_lock); 43802b553caSRafal Jaworowski 43902b553caSRafal Jaworowski return (0); 44002b553caSRafal Jaworowski } 44102b553caSRafal Jaworowski 44202b553caSRafal Jaworowski static int 44302b553caSRafal Jaworowski sec_suspend(device_t dev) 44402b553caSRafal Jaworowski { 44502b553caSRafal Jaworowski 44602b553caSRafal Jaworowski return (0); 44702b553caSRafal Jaworowski } 44802b553caSRafal Jaworowski 44902b553caSRafal Jaworowski static int 45002b553caSRafal Jaworowski sec_resume(device_t dev) 45102b553caSRafal Jaworowski { 45202b553caSRafal Jaworowski 45302b553caSRafal Jaworowski return (0); 45402b553caSRafal Jaworowski } 45502b553caSRafal Jaworowski 456661ee6eeSRafal Jaworowski static int 45702b553caSRafal Jaworowski sec_shutdown(device_t dev) 45802b553caSRafal Jaworowski { 459661ee6eeSRafal Jaworowski 460661ee6eeSRafal Jaworowski return (0); 46102b553caSRafal Jaworowski } 46202b553caSRafal Jaworowski 46302b553caSRafal Jaworowski static int 46402b553caSRafal Jaworowski sec_setup_intr(struct sec_softc *sc, struct resource **ires, void **ihand, 46502b553caSRafal Jaworowski int *irid, driver_intr_t handler, const char *iname) 46602b553caSRafal Jaworowski { 46702b553caSRafal Jaworowski int error; 46802b553caSRafal Jaworowski 46902b553caSRafal Jaworowski (*ires) = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, irid, 47002b553caSRafal Jaworowski RF_ACTIVE); 47102b553caSRafal Jaworowski 47202b553caSRafal Jaworowski if ((*ires) == NULL) { 47302b553caSRafal Jaworowski device_printf(sc->sc_dev, "could not allocate %s IRQ\n", iname); 47402b553caSRafal Jaworowski return (ENXIO); 47502b553caSRafal Jaworowski } 47602b553caSRafal Jaworowski 47702b553caSRafal Jaworowski error = bus_setup_intr(sc->sc_dev, *ires, INTR_MPSAFE | INTR_TYPE_NET, 47802b553caSRafal Jaworowski NULL, handler, sc, ihand); 47902b553caSRafal Jaworowski 48002b553caSRafal Jaworowski if (error) { 48102b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to set up %s IRQ\n", iname); 48202b553caSRafal Jaworowski if (bus_release_resource(sc->sc_dev, SYS_RES_IRQ, *irid, *ires)) 48302b553caSRafal Jaworowski device_printf(sc->sc_dev, "could not release %s IRQ\n", 48402b553caSRafal Jaworowski iname); 48502b553caSRafal Jaworowski 48602b553caSRafal Jaworowski (*ires) = NULL; 48702b553caSRafal Jaworowski return (error); 48802b553caSRafal Jaworowski } 48902b553caSRafal Jaworowski 49002b553caSRafal Jaworowski return (0); 49102b553caSRafal Jaworowski } 49202b553caSRafal Jaworowski 49302b553caSRafal Jaworowski static void 49402b553caSRafal Jaworowski sec_release_intr(struct sec_softc *sc, struct resource *ires, void *ihand, 49502b553caSRafal Jaworowski int irid, const char *iname) 49602b553caSRafal Jaworowski { 49702b553caSRafal Jaworowski int error; 49802b553caSRafal Jaworowski 49902b553caSRafal Jaworowski if (ires == NULL) 50002b553caSRafal Jaworowski return; 50102b553caSRafal Jaworowski 50202b553caSRafal Jaworowski error = bus_teardown_intr(sc->sc_dev, ires, ihand); 50302b553caSRafal Jaworowski if (error) 50402b553caSRafal Jaworowski device_printf(sc->sc_dev, "bus_teardown_intr() failed for %s" 50502b553caSRafal Jaworowski " IRQ, error %d\n", iname, error); 50602b553caSRafal Jaworowski 50702b553caSRafal Jaworowski error = bus_release_resource(sc->sc_dev, SYS_RES_IRQ, irid, ires); 50802b553caSRafal Jaworowski if (error) 50902b553caSRafal Jaworowski device_printf(sc->sc_dev, "bus_release_resource() failed for %s" 51002b553caSRafal Jaworowski " IRQ, error %d\n", iname, error); 51102b553caSRafal Jaworowski } 51202b553caSRafal Jaworowski 51302b553caSRafal Jaworowski static void 51402b553caSRafal Jaworowski sec_primary_intr(void *arg) 51502b553caSRafal Jaworowski { 516c0341432SJohn Baldwin struct sec_session *ses; 51702b553caSRafal Jaworowski struct sec_softc *sc = arg; 51802b553caSRafal Jaworowski struct sec_desc *desc; 519c0341432SJohn Baldwin struct cryptop *crp; 52002b553caSRafal Jaworowski uint64_t isr; 521c0341432SJohn Baldwin uint8_t hash[HASH_MAX_LEN]; 52202b553caSRafal Jaworowski int i, wakeup = 0; 52302b553caSRafal Jaworowski 52402b553caSRafal Jaworowski SEC_LOCK(sc, controller); 52502b553caSRafal Jaworowski 52602b553caSRafal Jaworowski /* Check for errors */ 52702b553caSRafal Jaworowski isr = SEC_READ(sc, SEC_ISR); 52802b553caSRafal Jaworowski if (isr & sc->sc_int_error_mask) { 52902b553caSRafal Jaworowski /* Check each channel for error */ 53002b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) { 53102b553caSRafal Jaworowski if ((isr & SEC_INT_CH_ERR(i)) == 0) 53202b553caSRafal Jaworowski continue; 53302b553caSRafal Jaworowski 53402b553caSRafal Jaworowski device_printf(sc->sc_dev, 53502b553caSRafal Jaworowski "I/O error on channel %i!\n", i); 53602b553caSRafal Jaworowski 53702b553caSRafal Jaworowski /* Find and mark problematic descriptor */ 53802b553caSRafal Jaworowski desc = sec_find_desc(sc, SEC_READ(sc, 53902b553caSRafal Jaworowski SEC_CHAN_CDPR(i))); 54002b553caSRafal Jaworowski 54102b553caSRafal Jaworowski if (desc != NULL) 54202b553caSRafal Jaworowski desc->sd_error = EIO; 54302b553caSRafal Jaworowski 54402b553caSRafal Jaworowski /* Do partial channel reset */ 54502b553caSRafal Jaworowski sec_channel_reset(sc, i, 0); 54602b553caSRafal Jaworowski } 54702b553caSRafal Jaworowski } 54802b553caSRafal Jaworowski 54902b553caSRafal Jaworowski /* ACK interrupt */ 55002b553caSRafal Jaworowski SEC_WRITE(sc, SEC_ICR, 0xFFFFFFFFFFFFFFFFULL); 55102b553caSRafal Jaworowski 55202b553caSRafal Jaworowski SEC_UNLOCK(sc, controller); 55302b553caSRafal Jaworowski SEC_LOCK(sc, descriptors); 55402b553caSRafal Jaworowski 55502b553caSRafal Jaworowski /* Handle processed descriptors */ 55602b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 55702b553caSRafal Jaworowski 55802b553caSRafal Jaworowski while (SEC_QUEUED_DESC_CNT(sc) > 0) { 55902b553caSRafal Jaworowski desc = SEC_GET_QUEUED_DESC(sc); 56002b553caSRafal Jaworowski 56102b553caSRafal Jaworowski if (desc->sd_desc->shd_done != 0xFF && desc->sd_error == 0) { 56202b553caSRafal Jaworowski SEC_PUT_BACK_QUEUED_DESC(sc); 56302b553caSRafal Jaworowski break; 56402b553caSRafal Jaworowski } 56502b553caSRafal Jaworowski 56602b553caSRafal Jaworowski SEC_DESC_SYNC_POINTERS(desc, BUS_DMASYNC_PREREAD | 56702b553caSRafal Jaworowski BUS_DMASYNC_PREWRITE); 56802b553caSRafal Jaworowski 569c0341432SJohn Baldwin crp = desc->sd_crp; 570c0341432SJohn Baldwin crp->crp_etype = desc->sd_error; 571c0341432SJohn Baldwin if (crp->crp_etype == 0) { 572c0341432SJohn Baldwin ses = crypto_get_driver_session(crp->crp_session); 573c0341432SJohn Baldwin if (ses->ss_mlen != 0) { 574c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { 575c0341432SJohn Baldwin crypto_copydata(crp, 576c0341432SJohn Baldwin crp->crp_digest_start, 577c0341432SJohn Baldwin ses->ss_mlen, hash); 578c0341432SJohn Baldwin if (timingsafe_bcmp( 579c0341432SJohn Baldwin desc->sd_desc->shd_digest, 580c0341432SJohn Baldwin hash, ses->ss_mlen) != 0) 581c0341432SJohn Baldwin crp->crp_etype = EBADMSG; 582c0341432SJohn Baldwin } else 583c0341432SJohn Baldwin crypto_copyback(crp, 584c0341432SJohn Baldwin crp->crp_digest_start, 585c0341432SJohn Baldwin ses->ss_mlen, 586c0341432SJohn Baldwin desc->sd_desc->shd_digest); 587c0341432SJohn Baldwin } 588c0341432SJohn Baldwin } 58902b553caSRafal Jaworowski crypto_done(desc->sd_crp); 59002b553caSRafal Jaworowski 59102b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(desc); 59202b553caSRafal Jaworowski SEC_DESC_FREE_LT(sc, desc); 59302b553caSRafal Jaworowski SEC_DESC_QUEUED2FREE(sc); 59402b553caSRafal Jaworowski } 59502b553caSRafal Jaworowski 59602b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 59702b553caSRafal Jaworowski 59802b553caSRafal Jaworowski if (!sc->sc_shutdown) { 59902b553caSRafal Jaworowski wakeup = sc->sc_blocked; 60002b553caSRafal Jaworowski sc->sc_blocked = 0; 60102b553caSRafal Jaworowski } 60202b553caSRafal Jaworowski 60302b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 60402b553caSRafal Jaworowski 60502b553caSRafal Jaworowski /* Enqueue ready descriptors in hardware */ 60602b553caSRafal Jaworowski sec_enqueue(sc); 60702b553caSRafal Jaworowski 60802b553caSRafal Jaworowski if (wakeup) 60902b553caSRafal Jaworowski crypto_unblock(sc->sc_cid, wakeup); 61002b553caSRafal Jaworowski } 61102b553caSRafal Jaworowski 61202b553caSRafal Jaworowski static void 61302b553caSRafal Jaworowski sec_secondary_intr(void *arg) 61402b553caSRafal Jaworowski { 61502b553caSRafal Jaworowski struct sec_softc *sc = arg; 61602b553caSRafal Jaworowski 61702b553caSRafal Jaworowski device_printf(sc->sc_dev, "spurious secondary interrupt!\n"); 61802b553caSRafal Jaworowski sec_primary_intr(arg); 61902b553caSRafal Jaworowski } 62002b553caSRafal Jaworowski 62102b553caSRafal Jaworowski static int 62202b553caSRafal Jaworowski sec_controller_reset(struct sec_softc *sc) 62302b553caSRafal Jaworowski { 62402b553caSRafal Jaworowski int timeout = SEC_TIMEOUT; 62502b553caSRafal Jaworowski 62602b553caSRafal Jaworowski /* Reset Controller */ 62702b553caSRafal Jaworowski SEC_WRITE(sc, SEC_MCR, SEC_MCR_SWR); 62802b553caSRafal Jaworowski 62902b553caSRafal Jaworowski while (SEC_READ(sc, SEC_MCR) & SEC_MCR_SWR) { 63002b553caSRafal Jaworowski DELAY(1000); 63102b553caSRafal Jaworowski timeout -= 1000; 63202b553caSRafal Jaworowski 63302b553caSRafal Jaworowski if (timeout < 0) { 63402b553caSRafal Jaworowski device_printf(sc->sc_dev, "timeout while waiting for " 63502b553caSRafal Jaworowski "device reset!\n"); 63602b553caSRafal Jaworowski return (ETIMEDOUT); 63702b553caSRafal Jaworowski } 63802b553caSRafal Jaworowski } 63902b553caSRafal Jaworowski 64002b553caSRafal Jaworowski return (0); 64102b553caSRafal Jaworowski } 64202b553caSRafal Jaworowski 64302b553caSRafal Jaworowski static int 64402b553caSRafal Jaworowski sec_channel_reset(struct sec_softc *sc, int channel, int full) 64502b553caSRafal Jaworowski { 64602b553caSRafal Jaworowski int timeout = SEC_TIMEOUT; 64702b553caSRafal Jaworowski uint64_t bit = (full) ? SEC_CHAN_CCR_R : SEC_CHAN_CCR_CON; 64802b553caSRafal Jaworowski uint64_t reg; 64902b553caSRafal Jaworowski 65002b553caSRafal Jaworowski /* Reset Channel */ 65102b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CCR(channel)); 65202b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_CCR(channel), reg | bit); 65302b553caSRafal Jaworowski 65402b553caSRafal Jaworowski while (SEC_READ(sc, SEC_CHAN_CCR(channel)) & bit) { 65502b553caSRafal Jaworowski DELAY(1000); 65602b553caSRafal Jaworowski timeout -= 1000; 65702b553caSRafal Jaworowski 65802b553caSRafal Jaworowski if (timeout < 0) { 65902b553caSRafal Jaworowski device_printf(sc->sc_dev, "timeout while waiting for " 66002b553caSRafal Jaworowski "channel reset!\n"); 66102b553caSRafal Jaworowski return (ETIMEDOUT); 66202b553caSRafal Jaworowski } 66302b553caSRafal Jaworowski } 66402b553caSRafal Jaworowski 66502b553caSRafal Jaworowski if (full) { 66602b553caSRafal Jaworowski reg = SEC_CHAN_CCR_CDIE | SEC_CHAN_CCR_NT | SEC_CHAN_CCR_BS; 66702b553caSRafal Jaworowski 66802b553caSRafal Jaworowski switch(sc->sc_version) { 66902b553caSRafal Jaworowski case 2: 67002b553caSRafal Jaworowski reg |= SEC_CHAN_CCR_CDWE; 67102b553caSRafal Jaworowski break; 67202b553caSRafal Jaworowski case 3: 67302b553caSRafal Jaworowski reg |= SEC_CHAN_CCR_AWSE | SEC_CHAN_CCR_WGN; 67402b553caSRafal Jaworowski break; 67502b553caSRafal Jaworowski } 67602b553caSRafal Jaworowski 67702b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_CCR(channel), reg); 67802b553caSRafal Jaworowski } 67902b553caSRafal Jaworowski 68002b553caSRafal Jaworowski return (0); 68102b553caSRafal Jaworowski } 68202b553caSRafal Jaworowski 68302b553caSRafal Jaworowski static int 68402b553caSRafal Jaworowski sec_init(struct sec_softc *sc) 68502b553caSRafal Jaworowski { 68602b553caSRafal Jaworowski uint64_t reg; 68702b553caSRafal Jaworowski int error, i; 68802b553caSRafal Jaworowski 68902b553caSRafal Jaworowski /* Reset controller twice to clear all pending interrupts */ 69002b553caSRafal Jaworowski error = sec_controller_reset(sc); 69102b553caSRafal Jaworowski if (error) 69202b553caSRafal Jaworowski return (error); 69302b553caSRafal Jaworowski 69402b553caSRafal Jaworowski error = sec_controller_reset(sc); 69502b553caSRafal Jaworowski if (error) 69602b553caSRafal Jaworowski return (error); 69702b553caSRafal Jaworowski 69802b553caSRafal Jaworowski /* Reset channels */ 69902b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) { 70002b553caSRafal Jaworowski error = sec_channel_reset(sc, i, 1); 70102b553caSRafal Jaworowski if (error) 70202b553caSRafal Jaworowski return (error); 70302b553caSRafal Jaworowski } 70402b553caSRafal Jaworowski 70502b553caSRafal Jaworowski /* Enable Interrupts */ 70602b553caSRafal Jaworowski reg = SEC_INT_ITO; 70702b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) 70802b553caSRafal Jaworowski reg |= SEC_INT_CH_DN(i) | SEC_INT_CH_ERR(i); 70902b553caSRafal Jaworowski 71002b553caSRafal Jaworowski SEC_WRITE(sc, SEC_IER, reg); 71102b553caSRafal Jaworowski 71202b553caSRafal Jaworowski return (error); 71302b553caSRafal Jaworowski } 71402b553caSRafal Jaworowski 71502b553caSRafal Jaworowski static void 71602b553caSRafal Jaworowski sec_alloc_dma_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 71702b553caSRafal Jaworowski { 71802b553caSRafal Jaworowski struct sec_dma_mem *dma_mem = arg; 71902b553caSRafal Jaworowski 72002b553caSRafal Jaworowski if (error) 72102b553caSRafal Jaworowski return; 72202b553caSRafal Jaworowski 72302b553caSRafal Jaworowski KASSERT(nseg == 1, ("Wrong number of segments, should be 1")); 72402b553caSRafal Jaworowski dma_mem->dma_paddr = segs->ds_addr; 72502b553caSRafal Jaworowski } 72602b553caSRafal Jaworowski 72702b553caSRafal Jaworowski static void 72802b553caSRafal Jaworowski sec_dma_map_desc_cb(void *arg, bus_dma_segment_t *segs, int nseg, 72902b553caSRafal Jaworowski int error) 73002b553caSRafal Jaworowski { 73102b553caSRafal Jaworowski struct sec_desc_map_info *sdmi = arg; 73202b553caSRafal Jaworowski struct sec_softc *sc = sdmi->sdmi_sc; 73302b553caSRafal Jaworowski struct sec_lt *lt = NULL; 73402b553caSRafal Jaworowski bus_addr_t addr; 73502b553caSRafal Jaworowski bus_size_t size; 73602b553caSRafal Jaworowski int i; 73702b553caSRafal Jaworowski 73802b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors); 73902b553caSRafal Jaworowski 74002b553caSRafal Jaworowski if (error) 74102b553caSRafal Jaworowski return; 74202b553caSRafal Jaworowski 74302b553caSRafal Jaworowski for (i = 0; i < nseg; i++) { 74402b553caSRafal Jaworowski addr = segs[i].ds_addr; 74502b553caSRafal Jaworowski size = segs[i].ds_len; 74602b553caSRafal Jaworowski 74702b553caSRafal Jaworowski /* Skip requested offset */ 74802b553caSRafal Jaworowski if (sdmi->sdmi_offset >= size) { 74902b553caSRafal Jaworowski sdmi->sdmi_offset -= size; 75002b553caSRafal Jaworowski continue; 75102b553caSRafal Jaworowski } 75202b553caSRafal Jaworowski 75302b553caSRafal Jaworowski addr += sdmi->sdmi_offset; 75402b553caSRafal Jaworowski size -= sdmi->sdmi_offset; 75502b553caSRafal Jaworowski sdmi->sdmi_offset = 0; 75602b553caSRafal Jaworowski 75702b553caSRafal Jaworowski /* Do not link more than requested */ 75802b553caSRafal Jaworowski if (sdmi->sdmi_size < size) 75902b553caSRafal Jaworowski size = sdmi->sdmi_size; 76002b553caSRafal Jaworowski 76102b553caSRafal Jaworowski lt = SEC_ALLOC_LT_ENTRY(sc); 76202b553caSRafal Jaworowski lt->sl_lt->shl_length = size; 76302b553caSRafal Jaworowski lt->sl_lt->shl_r = 0; 76402b553caSRafal Jaworowski lt->sl_lt->shl_n = 0; 76502b553caSRafal Jaworowski lt->sl_lt->shl_ptr = addr; 76602b553caSRafal Jaworowski 76702b553caSRafal Jaworowski if (sdmi->sdmi_lt_first == NULL) 76802b553caSRafal Jaworowski sdmi->sdmi_lt_first = lt; 76902b553caSRafal Jaworowski 77002b553caSRafal Jaworowski sdmi->sdmi_lt_used += 1; 77102b553caSRafal Jaworowski 77202b553caSRafal Jaworowski if ((sdmi->sdmi_size -= size) == 0) 77302b553caSRafal Jaworowski break; 77402b553caSRafal Jaworowski } 77502b553caSRafal Jaworowski 77602b553caSRafal Jaworowski sdmi->sdmi_lt_last = lt; 77702b553caSRafal Jaworowski } 77802b553caSRafal Jaworowski 77902b553caSRafal Jaworowski static int 78002b553caSRafal Jaworowski sec_alloc_dma_mem(struct sec_softc *sc, struct sec_dma_mem *dma_mem, 78102b553caSRafal Jaworowski bus_size_t size) 78202b553caSRafal Jaworowski { 78302b553caSRafal Jaworowski int error; 78402b553caSRafal Jaworowski 78502b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL) 78602b553caSRafal Jaworowski return (EBUSY); 78702b553caSRafal Jaworowski 78802b553caSRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */ 78902b553caSRafal Jaworowski SEC_DMA_ALIGNMENT, 0, /* alignment, boundary */ 79002b553caSRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 79102b553caSRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */ 79202b553caSRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */ 79302b553caSRafal Jaworowski size, 1, /* maxsize, nsegments */ 79402b553caSRafal Jaworowski size, 0, /* maxsegsz, flags */ 79502b553caSRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */ 79602b553caSRafal Jaworowski &(dma_mem->dma_tag)); /* dmat */ 79702b553caSRafal Jaworowski 79802b553caSRafal Jaworowski if (error) { 79902b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate busdma tag, error" 80002b553caSRafal Jaworowski " %i!\n", error); 80102b553caSRafal Jaworowski goto err1; 80202b553caSRafal Jaworowski } 80302b553caSRafal Jaworowski 80402b553caSRafal Jaworowski error = bus_dmamem_alloc(dma_mem->dma_tag, &(dma_mem->dma_vaddr), 80502b553caSRafal Jaworowski BUS_DMA_NOWAIT | BUS_DMA_ZERO, &(dma_mem->dma_map)); 80602b553caSRafal Jaworowski 80702b553caSRafal Jaworowski if (error) { 80802b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate DMA safe" 80902b553caSRafal Jaworowski " memory, error %i!\n", error); 81002b553caSRafal Jaworowski goto err2; 81102b553caSRafal Jaworowski } 81202b553caSRafal Jaworowski 81302b553caSRafal Jaworowski error = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, 81402b553caSRafal Jaworowski dma_mem->dma_vaddr, size, sec_alloc_dma_mem_cb, dma_mem, 81502b553caSRafal Jaworowski BUS_DMA_NOWAIT); 81602b553caSRafal Jaworowski 81702b553caSRafal Jaworowski if (error) { 81802b553caSRafal Jaworowski device_printf(sc->sc_dev, "cannot get address of the DMA" 81902b553caSRafal Jaworowski " memory, error %i\n", error); 82002b553caSRafal Jaworowski goto err3; 82102b553caSRafal Jaworowski } 82202b553caSRafal Jaworowski 82302b553caSRafal Jaworowski dma_mem->dma_is_map = 0; 82402b553caSRafal Jaworowski return (0); 82502b553caSRafal Jaworowski 82602b553caSRafal Jaworowski err3: 82702b553caSRafal Jaworowski bus_dmamem_free(dma_mem->dma_tag, dma_mem->dma_vaddr, dma_mem->dma_map); 82802b553caSRafal Jaworowski err2: 82902b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag); 83002b553caSRafal Jaworowski err1: 83102b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL; 83202b553caSRafal Jaworowski return(error); 83302b553caSRafal Jaworowski } 83402b553caSRafal Jaworowski 83502b553caSRafal Jaworowski static int 836c0341432SJohn Baldwin sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem, 837c0341432SJohn Baldwin struct cryptop *crp, bus_size_t size, struct sec_desc_map_info *sdmi) 83802b553caSRafal Jaworowski { 83902b553caSRafal Jaworowski int error; 84002b553caSRafal Jaworowski 84102b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL) 84202b553caSRafal Jaworowski return (EBUSY); 84302b553caSRafal Jaworowski 844b02676a2SJohn Baldwin switch (crp->crp_buf.cb_type) { 845c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 84602b553caSRafal Jaworowski break; 847c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 84802b553caSRafal Jaworowski size = SEC_FREE_LT_CNT(sc) * SEC_MAX_DMA_BLOCK_SIZE; 84902b553caSRafal Jaworowski break; 850c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 851b02676a2SJohn Baldwin size = m_length(crp->crp_buf.cb_mbuf, NULL); 85202b553caSRafal Jaworowski break; 853*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 854*883a0196SJohn Baldwin size = crp->crp_buf.cb_mbuf->m_len; 855*883a0196SJohn Baldwin break; 856e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 8572941010bSBrandon Bergren size = PAGE_SIZE - crp->crp_buf.cb_vm_page_offset; 858e6f6d0c9SAlan Somers break; 85902b553caSRafal Jaworowski default: 86002b553caSRafal Jaworowski return (EINVAL); 86102b553caSRafal Jaworowski } 86202b553caSRafal Jaworowski 86302b553caSRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */ 86402b553caSRafal Jaworowski SEC_DMA_ALIGNMENT, 0, /* alignment, boundary */ 86502b553caSRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 86602b553caSRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */ 86702b553caSRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */ 86802b553caSRafal Jaworowski size, /* maxsize */ 86902b553caSRafal Jaworowski SEC_FREE_LT_CNT(sc), /* nsegments */ 87002b553caSRafal Jaworowski SEC_MAX_DMA_BLOCK_SIZE, 0, /* maxsegsz, flags */ 87102b553caSRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */ 87202b553caSRafal Jaworowski &(dma_mem->dma_tag)); /* dmat */ 87302b553caSRafal Jaworowski 87402b553caSRafal Jaworowski if (error) { 87502b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate busdma tag, error" 87602b553caSRafal Jaworowski " %i!\n", error); 87702b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL; 87802b553caSRafal Jaworowski return (error); 87902b553caSRafal Jaworowski } 88002b553caSRafal Jaworowski 88102b553caSRafal Jaworowski error = bus_dmamap_create(dma_mem->dma_tag, 0, &(dma_mem->dma_map)); 88202b553caSRafal Jaworowski 88302b553caSRafal Jaworowski if (error) { 88402b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to create DMA map, error %i!" 88502b553caSRafal Jaworowski "\n", error); 88602b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag); 88702b553caSRafal Jaworowski return (error); 88802b553caSRafal Jaworowski } 88902b553caSRafal Jaworowski 890c0341432SJohn Baldwin error = bus_dmamap_load_crp(dma_mem->dma_tag, dma_mem->dma_map, crp, 891c0341432SJohn Baldwin sec_dma_map_desc_cb, sdmi, BUS_DMA_NOWAIT); 89202b553caSRafal Jaworowski 89302b553caSRafal Jaworowski if (error) { 89402b553caSRafal Jaworowski device_printf(sc->sc_dev, "cannot get address of the DMA" 89502b553caSRafal Jaworowski " memory, error %i!\n", error); 89602b553caSRafal Jaworowski bus_dmamap_destroy(dma_mem->dma_tag, dma_mem->dma_map); 89702b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag); 89802b553caSRafal Jaworowski return (error); 89902b553caSRafal Jaworowski } 90002b553caSRafal Jaworowski 90102b553caSRafal Jaworowski dma_mem->dma_is_map = 1; 902c0341432SJohn Baldwin dma_mem->dma_vaddr = crp; 90302b553caSRafal Jaworowski 90402b553caSRafal Jaworowski return (0); 90502b553caSRafal Jaworowski } 90602b553caSRafal Jaworowski 90702b553caSRafal Jaworowski static void 90802b553caSRafal Jaworowski sec_free_dma_mem(struct sec_dma_mem *dma_mem) 90902b553caSRafal Jaworowski { 91002b553caSRafal Jaworowski 91102b553caSRafal Jaworowski /* Check for double free */ 91202b553caSRafal Jaworowski if (dma_mem->dma_vaddr == NULL) 91302b553caSRafal Jaworowski return; 91402b553caSRafal Jaworowski 91502b553caSRafal Jaworowski bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); 91602b553caSRafal Jaworowski 91702b553caSRafal Jaworowski if (dma_mem->dma_is_map) 91802b553caSRafal Jaworowski bus_dmamap_destroy(dma_mem->dma_tag, dma_mem->dma_map); 91902b553caSRafal Jaworowski else 92002b553caSRafal Jaworowski bus_dmamem_free(dma_mem->dma_tag, dma_mem->dma_vaddr, 92102b553caSRafal Jaworowski dma_mem->dma_map); 92202b553caSRafal Jaworowski 92302b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag); 92402b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL; 92502b553caSRafal Jaworowski } 92602b553caSRafal Jaworowski 92702b553caSRafal Jaworowski static int 92802b553caSRafal Jaworowski sec_eu_channel(struct sec_softc *sc, int eu) 92902b553caSRafal Jaworowski { 93002b553caSRafal Jaworowski uint64_t reg; 93102b553caSRafal Jaworowski int channel = 0; 93202b553caSRafal Jaworowski 93302b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, controller); 93402b553caSRafal Jaworowski 93502b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_EUASR); 93602b553caSRafal Jaworowski 93702b553caSRafal Jaworowski switch (eu) { 93802b553caSRafal Jaworowski case SEC_EU_AFEU: 93902b553caSRafal Jaworowski channel = SEC_EUASR_AFEU(reg); 94002b553caSRafal Jaworowski break; 94102b553caSRafal Jaworowski case SEC_EU_DEU: 94202b553caSRafal Jaworowski channel = SEC_EUASR_DEU(reg); 94302b553caSRafal Jaworowski break; 94402b553caSRafal Jaworowski case SEC_EU_MDEU_A: 94502b553caSRafal Jaworowski case SEC_EU_MDEU_B: 94602b553caSRafal Jaworowski channel = SEC_EUASR_MDEU(reg); 94702b553caSRafal Jaworowski break; 94802b553caSRafal Jaworowski case SEC_EU_RNGU: 94902b553caSRafal Jaworowski channel = SEC_EUASR_RNGU(reg); 95002b553caSRafal Jaworowski break; 95102b553caSRafal Jaworowski case SEC_EU_PKEU: 95202b553caSRafal Jaworowski channel = SEC_EUASR_PKEU(reg); 95302b553caSRafal Jaworowski break; 95402b553caSRafal Jaworowski case SEC_EU_AESU: 95502b553caSRafal Jaworowski channel = SEC_EUASR_AESU(reg); 95602b553caSRafal Jaworowski break; 95702b553caSRafal Jaworowski case SEC_EU_KEU: 95802b553caSRafal Jaworowski channel = SEC_EUASR_KEU(reg); 95902b553caSRafal Jaworowski break; 96002b553caSRafal Jaworowski case SEC_EU_CRCU: 96102b553caSRafal Jaworowski channel = SEC_EUASR_CRCU(reg); 96202b553caSRafal Jaworowski break; 96302b553caSRafal Jaworowski } 96402b553caSRafal Jaworowski 96502b553caSRafal Jaworowski return (channel - 1); 96602b553caSRafal Jaworowski } 96702b553caSRafal Jaworowski 96802b553caSRafal Jaworowski static int 96902b553caSRafal Jaworowski sec_enqueue_desc(struct sec_softc *sc, struct sec_desc *desc, int channel) 97002b553caSRafal Jaworowski { 97102b553caSRafal Jaworowski u_int fflvl = SEC_MAX_FIFO_LEVEL; 97202b553caSRafal Jaworowski uint64_t reg; 97302b553caSRafal Jaworowski int i; 97402b553caSRafal Jaworowski 97502b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, controller); 97602b553caSRafal Jaworowski 97702b553caSRafal Jaworowski /* Find free channel if have not got one */ 97802b553caSRafal Jaworowski if (channel < 0) { 97902b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) { 98002b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CSR(channel)); 98102b553caSRafal Jaworowski 98202b553caSRafal Jaworowski if ((reg & sc->sc_channel_idle_mask) == 0) { 98302b553caSRafal Jaworowski channel = i; 98402b553caSRafal Jaworowski break; 98502b553caSRafal Jaworowski } 98602b553caSRafal Jaworowski } 98702b553caSRafal Jaworowski } 98802b553caSRafal Jaworowski 98902b553caSRafal Jaworowski /* There is no free channel */ 99002b553caSRafal Jaworowski if (channel < 0) 99102b553caSRafal Jaworowski return (-1); 99202b553caSRafal Jaworowski 99302b553caSRafal Jaworowski /* Check FIFO level on selected channel */ 99402b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CSR(channel)); 99502b553caSRafal Jaworowski 99602b553caSRafal Jaworowski switch(sc->sc_version) { 99702b553caSRafal Jaworowski case 2: 99802b553caSRafal Jaworowski fflvl = (reg >> SEC_CHAN_CSR2_FFLVL_S) & SEC_CHAN_CSR2_FFLVL_M; 99902b553caSRafal Jaworowski break; 100002b553caSRafal Jaworowski case 3: 100102b553caSRafal Jaworowski fflvl = (reg >> SEC_CHAN_CSR3_FFLVL_S) & SEC_CHAN_CSR3_FFLVL_M; 100202b553caSRafal Jaworowski break; 100302b553caSRafal Jaworowski } 100402b553caSRafal Jaworowski 100502b553caSRafal Jaworowski if (fflvl >= SEC_MAX_FIFO_LEVEL) 100602b553caSRafal Jaworowski return (-1); 100702b553caSRafal Jaworowski 100802b553caSRafal Jaworowski /* Enqueue descriptor in channel */ 100902b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_FF(channel), desc->sd_desc_paddr); 101002b553caSRafal Jaworowski 101102b553caSRafal Jaworowski return (channel); 101202b553caSRafal Jaworowski } 101302b553caSRafal Jaworowski 101402b553caSRafal Jaworowski static void 101502b553caSRafal Jaworowski sec_enqueue(struct sec_softc *sc) 101602b553caSRafal Jaworowski { 101702b553caSRafal Jaworowski struct sec_desc *desc; 101802b553caSRafal Jaworowski int ch0, ch1; 101902b553caSRafal Jaworowski 102002b553caSRafal Jaworowski SEC_LOCK(sc, descriptors); 102102b553caSRafal Jaworowski SEC_LOCK(sc, controller); 102202b553caSRafal Jaworowski 102302b553caSRafal Jaworowski while (SEC_READY_DESC_CNT(sc) > 0) { 102402b553caSRafal Jaworowski desc = SEC_GET_READY_DESC(sc); 102502b553caSRafal Jaworowski 102602b553caSRafal Jaworowski ch0 = sec_eu_channel(sc, desc->sd_desc->shd_eu_sel0); 102702b553caSRafal Jaworowski ch1 = sec_eu_channel(sc, desc->sd_desc->shd_eu_sel1); 102802b553caSRafal Jaworowski 102902b553caSRafal Jaworowski /* 103002b553caSRafal Jaworowski * Both EU are used by the same channel. 103102b553caSRafal Jaworowski * Enqueue descriptor in channel used by busy EUs. 103202b553caSRafal Jaworowski */ 103302b553caSRafal Jaworowski if (ch0 >= 0 && ch0 == ch1) { 103402b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, ch0) >= 0) { 103502b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc); 103602b553caSRafal Jaworowski continue; 103702b553caSRafal Jaworowski } 103802b553caSRafal Jaworowski } 103902b553caSRafal Jaworowski 104002b553caSRafal Jaworowski /* 104102b553caSRafal Jaworowski * Only one EU is free. 104202b553caSRafal Jaworowski * Enqueue descriptor in channel used by busy EU. 104302b553caSRafal Jaworowski */ 104402b553caSRafal Jaworowski if ((ch0 >= 0 && ch1 < 0) || (ch1 >= 0 && ch0 < 0)) { 104502b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, (ch0 >= 0) ? ch0 : ch1) 104602b553caSRafal Jaworowski >= 0) { 104702b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc); 104802b553caSRafal Jaworowski continue; 104902b553caSRafal Jaworowski } 105002b553caSRafal Jaworowski } 105102b553caSRafal Jaworowski 105202b553caSRafal Jaworowski /* 105302b553caSRafal Jaworowski * Both EU are free. 105402b553caSRafal Jaworowski * Enqueue descriptor in first free channel. 105502b553caSRafal Jaworowski */ 105602b553caSRafal Jaworowski if (ch0 < 0 && ch1 < 0) { 105702b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, -1) >= 0) { 105802b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc); 105902b553caSRafal Jaworowski continue; 106002b553caSRafal Jaworowski } 106102b553caSRafal Jaworowski } 106202b553caSRafal Jaworowski 106302b553caSRafal Jaworowski /* Current descriptor can not be queued at the moment */ 106402b553caSRafal Jaworowski SEC_PUT_BACK_READY_DESC(sc); 106502b553caSRafal Jaworowski break; 106602b553caSRafal Jaworowski } 106702b553caSRafal Jaworowski 106802b553caSRafal Jaworowski SEC_UNLOCK(sc, controller); 106902b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 107002b553caSRafal Jaworowski } 107102b553caSRafal Jaworowski 107202b553caSRafal Jaworowski static struct sec_desc * 107302b553caSRafal Jaworowski sec_find_desc(struct sec_softc *sc, bus_addr_t paddr) 107402b553caSRafal Jaworowski { 107502b553caSRafal Jaworowski struct sec_desc *desc = NULL; 107602b553caSRafal Jaworowski int i; 107702b553caSRafal Jaworowski 107802b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors); 107902b553caSRafal Jaworowski 108002b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) { 108102b553caSRafal Jaworowski if (sc->sc_desc[i].sd_desc_paddr == paddr) { 108202b553caSRafal Jaworowski desc = &(sc->sc_desc[i]); 108302b553caSRafal Jaworowski break; 108402b553caSRafal Jaworowski } 108502b553caSRafal Jaworowski } 108602b553caSRafal Jaworowski 108702b553caSRafal Jaworowski return (desc); 108802b553caSRafal Jaworowski } 108902b553caSRafal Jaworowski 109002b553caSRafal Jaworowski static int 109102b553caSRafal Jaworowski sec_make_pointer_direct(struct sec_softc *sc, struct sec_desc *desc, u_int n, 109202b553caSRafal Jaworowski bus_addr_t data, bus_size_t dsize) 109302b553caSRafal Jaworowski { 109402b553caSRafal Jaworowski struct sec_hw_desc_ptr *ptr; 109502b553caSRafal Jaworowski 109602b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors); 109702b553caSRafal Jaworowski 109802b553caSRafal Jaworowski ptr = &(desc->sd_desc->shd_pointer[n]); 109902b553caSRafal Jaworowski ptr->shdp_length = dsize; 110002b553caSRafal Jaworowski ptr->shdp_extent = 0; 110102b553caSRafal Jaworowski ptr->shdp_j = 0; 110202b553caSRafal Jaworowski ptr->shdp_ptr = data; 110302b553caSRafal Jaworowski 110402b553caSRafal Jaworowski return (0); 110502b553caSRafal Jaworowski } 110602b553caSRafal Jaworowski 110702b553caSRafal Jaworowski static int 110802b553caSRafal Jaworowski sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc, 1109c0341432SJohn Baldwin u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize) 111002b553caSRafal Jaworowski { 111102b553caSRafal Jaworowski struct sec_desc_map_info sdmi = { sc, dsize, doffset, NULL, NULL, 0 }; 111202b553caSRafal Jaworowski struct sec_hw_desc_ptr *ptr; 111302b553caSRafal Jaworowski int error; 111402b553caSRafal Jaworowski 111502b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors); 111602b553caSRafal Jaworowski 1117c0341432SJohn Baldwin error = sec_desc_map_dma(sc, &(desc->sd_ptr_dmem[n]), crp, dsize, 1118c0341432SJohn Baldwin &sdmi); 111902b553caSRafal Jaworowski 112002b553caSRafal Jaworowski if (error) 112102b553caSRafal Jaworowski return (error); 112202b553caSRafal Jaworowski 112302b553caSRafal Jaworowski sdmi.sdmi_lt_last->sl_lt->shl_r = 1; 112402b553caSRafal Jaworowski desc->sd_lt_used += sdmi.sdmi_lt_used; 112502b553caSRafal Jaworowski 112602b553caSRafal Jaworowski ptr = &(desc->sd_desc->shd_pointer[n]); 112702b553caSRafal Jaworowski ptr->shdp_length = dsize; 112802b553caSRafal Jaworowski ptr->shdp_extent = 0; 112902b553caSRafal Jaworowski ptr->shdp_j = 1; 113002b553caSRafal Jaworowski ptr->shdp_ptr = sdmi.sdmi_lt_first->sl_lt_paddr; 113102b553caSRafal Jaworowski 113202b553caSRafal Jaworowski return (0); 113302b553caSRafal Jaworowski } 113402b553caSRafal Jaworowski 1135c0341432SJohn Baldwin static bool 1136c0341432SJohn Baldwin sec_cipher_supported(const struct crypto_session_params *csp) 113702b553caSRafal Jaworowski { 113802b553caSRafal Jaworowski 1139c0341432SJohn Baldwin switch (csp->csp_cipher_alg) { 1140c0341432SJohn Baldwin case CRYPTO_AES_CBC: 1141c0341432SJohn Baldwin /* AESU */ 1142c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN) 1143c0341432SJohn Baldwin return (false); 1144c0341432SJohn Baldwin break; 1145c0341432SJohn Baldwin default: 1146c0341432SJohn Baldwin return (false); 114702b553caSRafal Jaworowski } 114802b553caSRafal Jaworowski 1149c0341432SJohn Baldwin if (csp->csp_cipher_klen == 0 || csp->csp_cipher_klen > SEC_MAX_KEY_LEN) 1150c0341432SJohn Baldwin return (false); 115102b553caSRafal Jaworowski 1152c0341432SJohn Baldwin return (true); 115302b553caSRafal Jaworowski } 115402b553caSRafal Jaworowski 1155c0341432SJohn Baldwin static bool 1156c0341432SJohn Baldwin sec_auth_supported(struct sec_softc *sc, 1157c0341432SJohn Baldwin const struct crypto_session_params *csp) 115802b553caSRafal Jaworowski { 115902b553caSRafal Jaworowski 1160c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 1161c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC: 1162c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC: 1163c0341432SJohn Baldwin if (sc->sc_version < 3) 1164c0341432SJohn Baldwin return (false); 1165c0341432SJohn Baldwin /* FALLTHROUGH */ 1166c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC: 1167c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC: 1168c0341432SJohn Baldwin if (csp->csp_auth_klen > SEC_MAX_KEY_LEN) 1169c0341432SJohn Baldwin return (false); 1170c0341432SJohn Baldwin break; 1171c0341432SJohn Baldwin case CRYPTO_SHA1: 1172c0341432SJohn Baldwin break; 1173c0341432SJohn Baldwin default: 1174c0341432SJohn Baldwin return (false); 117502b553caSRafal Jaworowski } 1176c0341432SJohn Baldwin return (true); 117702b553caSRafal Jaworowski } 117802b553caSRafal Jaworowski 117902b553caSRafal Jaworowski static int 1180c0341432SJohn Baldwin sec_probesession(device_t dev, const struct crypto_session_params *csp) 118102b553caSRafal Jaworowski { 118202b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev); 1183c0341432SJohn Baldwin 1184c0341432SJohn Baldwin if (csp->csp_flags != 0) 1185c0341432SJohn Baldwin return (EINVAL); 1186c0341432SJohn Baldwin switch (csp->csp_mode) { 1187c0341432SJohn Baldwin case CSP_MODE_DIGEST: 1188c0341432SJohn Baldwin if (!sec_auth_supported(sc, csp)) 1189c0341432SJohn Baldwin return (EINVAL); 1190c0341432SJohn Baldwin break; 1191c0341432SJohn Baldwin case CSP_MODE_CIPHER: 1192c0341432SJohn Baldwin if (!sec_cipher_supported(csp)) 1193c0341432SJohn Baldwin return (EINVAL); 1194c0341432SJohn Baldwin break; 1195c0341432SJohn Baldwin case CSP_MODE_ETA: 1196c0341432SJohn Baldwin if (!sec_auth_supported(sc, csp) || !sec_cipher_supported(csp)) 1197c0341432SJohn Baldwin return (EINVAL); 1198c0341432SJohn Baldwin break; 1199c0341432SJohn Baldwin default: 1200c0341432SJohn Baldwin return (EINVAL); 1201c0341432SJohn Baldwin } 1202c0341432SJohn Baldwin return (CRYPTODEV_PROBE_HARDWARE); 1203c0341432SJohn Baldwin } 1204c0341432SJohn Baldwin 1205c0341432SJohn Baldwin static int 1206c0341432SJohn Baldwin sec_newsession(device_t dev, crypto_session_t cses, 1207c0341432SJohn Baldwin const struct crypto_session_params *csp) 1208c0341432SJohn Baldwin { 120902b553caSRafal Jaworowski struct sec_eu_methods *eu = sec_eus; 121002b553caSRafal Jaworowski struct sec_session *ses; 121102b553caSRafal Jaworowski 12121b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 121302b553caSRafal Jaworowski 121402b553caSRafal Jaworowski /* Find EU for this session */ 121502b553caSRafal Jaworowski while (eu->sem_make_desc != NULL) { 1216c0341432SJohn Baldwin if (eu->sem_newsession(csp)) 121702b553caSRafal Jaworowski break; 121802b553caSRafal Jaworowski eu++; 121902b553caSRafal Jaworowski } 1220c0341432SJohn Baldwin KASSERT(eu->sem_make_desc != NULL, ("failed to find eu for session")); 122102b553caSRafal Jaworowski 122202b553caSRafal Jaworowski /* Save cipher key */ 1223c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL) 1224c0341432SJohn Baldwin memcpy(ses->ss_key, csp->csp_cipher_key, csp->csp_cipher_klen); 122502b553caSRafal Jaworowski 122602b553caSRafal Jaworowski /* Save digest key */ 1227c0341432SJohn Baldwin if (csp->csp_auth_key != NULL) 1228c0341432SJohn Baldwin memcpy(ses->ss_mkey, csp->csp_auth_key, csp->csp_auth_klen); 1229c0341432SJohn Baldwin 1230c0341432SJohn Baldwin if (csp->csp_auth_alg != 0) { 1231c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0) 1232c0341432SJohn Baldwin ses->ss_mlen = crypto_auth_hash(csp)->hashsize; 1233c0341432SJohn Baldwin else 1234c0341432SJohn Baldwin ses->ss_mlen = csp->csp_auth_mlen; 123502b553caSRafal Jaworowski } 123602b553caSRafal Jaworowski 123702b553caSRafal Jaworowski return (0); 123802b553caSRafal Jaworowski } 123902b553caSRafal Jaworowski 124002b553caSRafal Jaworowski static int 124102b553caSRafal Jaworowski sec_process(device_t dev, struct cryptop *crp, int hint) 124202b553caSRafal Jaworowski { 124302b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev); 124402b553caSRafal Jaworowski struct sec_desc *desc = NULL; 1245c0341432SJohn Baldwin const struct crypto_session_params *csp; 124602b553caSRafal Jaworowski struct sec_session *ses; 1247c0341432SJohn Baldwin int error = 0; 124802b553caSRafal Jaworowski 12491b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1250c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session); 125102b553caSRafal Jaworowski 125202b553caSRafal Jaworowski /* Check for input length */ 1253b02676a2SJohn Baldwin if (crypto_buffer_len(&crp->crp_buf) > SEC_MAX_DMA_BLOCK_SIZE) { 125402b553caSRafal Jaworowski crp->crp_etype = E2BIG; 125502b553caSRafal Jaworowski crypto_done(crp); 125602b553caSRafal Jaworowski return (0); 125702b553caSRafal Jaworowski } 125802b553caSRafal Jaworowski 125902b553caSRafal Jaworowski SEC_LOCK(sc, descriptors); 126002b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 126102b553caSRafal Jaworowski 126202b553caSRafal Jaworowski /* Block driver if there is no free descriptors or we are going down */ 126302b553caSRafal Jaworowski if (SEC_FREE_DESC_CNT(sc) == 0 || sc->sc_shutdown) { 126402b553caSRafal Jaworowski sc->sc_blocked |= CRYPTO_SYMQ; 126502b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 126602b553caSRafal Jaworowski return (ERESTART); 126702b553caSRafal Jaworowski } 126802b553caSRafal Jaworowski 126902b553caSRafal Jaworowski /* Prepare descriptor */ 127002b553caSRafal Jaworowski desc = SEC_GET_FREE_DESC(sc); 127102b553caSRafal Jaworowski desc->sd_lt_used = 0; 127202b553caSRafal Jaworowski desc->sd_error = 0; 127302b553caSRafal Jaworowski desc->sd_crp = crp; 127402b553caSRafal Jaworowski 127529fe41ddSJohn Baldwin if (csp->csp_cipher_alg != 0) 127629fe41ddSJohn Baldwin crypto_read_iv(crp, desc->sd_desc->shd_iv); 127702b553caSRafal Jaworowski 1278c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL) 1279c0341432SJohn Baldwin memcpy(ses->ss_key, crp->crp_cipher_key, csp->csp_cipher_klen); 128002b553caSRafal Jaworowski 1281c0341432SJohn Baldwin if (crp->crp_auth_key != NULL) 1282c0341432SJohn Baldwin memcpy(ses->ss_mkey, crp->crp_auth_key, csp->csp_auth_klen); 128302b553caSRafal Jaworowski 1284c0341432SJohn Baldwin memcpy(desc->sd_desc->shd_key, ses->ss_key, csp->csp_cipher_klen); 1285c0341432SJohn Baldwin memcpy(desc->sd_desc->shd_mkey, ses->ss_mkey, csp->csp_auth_klen); 128602b553caSRafal Jaworowski 1287c0341432SJohn Baldwin error = ses->ss_eu->sem_make_desc(sc, csp, desc, crp); 128802b553caSRafal Jaworowski 128902b553caSRafal Jaworowski if (error) { 129002b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(desc); 129102b553caSRafal Jaworowski SEC_DESC_PUT_BACK_LT(sc, desc); 129202b553caSRafal Jaworowski SEC_PUT_BACK_FREE_DESC(sc); 129302b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 129402b553caSRafal Jaworowski crp->crp_etype = error; 129502b553caSRafal Jaworowski crypto_done(crp); 129602b553caSRafal Jaworowski return (0); 129702b553caSRafal Jaworowski } 129802b553caSRafal Jaworowski 129902b553caSRafal Jaworowski /* 130002b553caSRafal Jaworowski * Skip DONE interrupt if this is not last request in burst, but only 130102b553caSRafal Jaworowski * if we are running on SEC 3.X. On SEC 2.X we have to enable DONE 130202b553caSRafal Jaworowski * signaling on each descriptor. 130302b553caSRafal Jaworowski */ 130402b553caSRafal Jaworowski if ((hint & CRYPTO_HINT_MORE) && sc->sc_version == 3) 130502b553caSRafal Jaworowski desc->sd_desc->shd_dn = 0; 130602b553caSRafal Jaworowski else 130702b553caSRafal Jaworowski desc->sd_desc->shd_dn = 1; 130802b553caSRafal Jaworowski 130902b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 131002b553caSRafal Jaworowski SEC_DESC_SYNC_POINTERS(desc, BUS_DMASYNC_POSTREAD | 131102b553caSRafal Jaworowski BUS_DMASYNC_POSTWRITE); 131202b553caSRafal Jaworowski SEC_DESC_FREE2READY(sc); 131302b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors); 131402b553caSRafal Jaworowski 131502b553caSRafal Jaworowski /* Enqueue ready descriptors in hardware */ 131602b553caSRafal Jaworowski sec_enqueue(sc); 131702b553caSRafal Jaworowski 131802b553caSRafal Jaworowski return (0); 131902b553caSRafal Jaworowski } 132002b553caSRafal Jaworowski 132102b553caSRafal Jaworowski static int 132202b553caSRafal Jaworowski sec_build_common_ns_desc(struct sec_softc *sc, struct sec_desc *desc, 1323c0341432SJohn Baldwin const struct crypto_session_params *csp, struct cryptop *crp) 132402b553caSRafal Jaworowski { 132502b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc; 132602b553caSRafal Jaworowski int error; 132702b553caSRafal Jaworowski 132802b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_COMMON_NONSNOOP; 132902b553caSRafal Jaworowski hd->shd_eu_sel1 = SEC_EU_NONE; 133002b553caSRafal Jaworowski hd->shd_mode1 = 0; 133102b553caSRafal Jaworowski 133202b553caSRafal Jaworowski /* Pointer 0: NULL */ 133302b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, 0, 0); 133402b553caSRafal Jaworowski if (error) 133502b553caSRafal Jaworowski return (error); 133602b553caSRafal Jaworowski 133702b553caSRafal Jaworowski /* Pointer 1: IV IN */ 133802b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 1, desc->sd_desc_paddr + 1339c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen); 134002b553caSRafal Jaworowski if (error) 134102b553caSRafal Jaworowski return (error); 134202b553caSRafal Jaworowski 134302b553caSRafal Jaworowski /* Pointer 2: Cipher Key */ 134402b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr + 1345c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen); 134602b553caSRafal Jaworowski if (error) 134702b553caSRafal Jaworowski return (error); 134802b553caSRafal Jaworowski 134902b553caSRafal Jaworowski /* Pointer 3: Data IN */ 1350c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start, 1351c0341432SJohn Baldwin crp->crp_payload_length); 135202b553caSRafal Jaworowski if (error) 135302b553caSRafal Jaworowski return (error); 135402b553caSRafal Jaworowski 135502b553caSRafal Jaworowski /* Pointer 4: Data OUT */ 1356c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start, 1357c0341432SJohn Baldwin crp->crp_payload_length); 135802b553caSRafal Jaworowski if (error) 135902b553caSRafal Jaworowski return (error); 136002b553caSRafal Jaworowski 136102b553caSRafal Jaworowski /* Pointer 5: IV OUT (Not used: NULL) */ 136202b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 5, 0, 0); 136302b553caSRafal Jaworowski if (error) 136402b553caSRafal Jaworowski return (error); 136502b553caSRafal Jaworowski 136602b553caSRafal Jaworowski /* Pointer 6: NULL */ 136702b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 6, 0, 0); 136802b553caSRafal Jaworowski 136902b553caSRafal Jaworowski return (error); 137002b553caSRafal Jaworowski } 137102b553caSRafal Jaworowski 137202b553caSRafal Jaworowski static int 137302b553caSRafal Jaworowski sec_build_common_s_desc(struct sec_softc *sc, struct sec_desc *desc, 1374c0341432SJohn Baldwin const struct crypto_session_params *csp, struct cryptop *crp) 137502b553caSRafal Jaworowski { 137602b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc; 137702b553caSRafal Jaworowski u_int eu, mode, hashlen; 137802b553caSRafal Jaworowski int error; 137902b553caSRafal Jaworowski 1380c0341432SJohn Baldwin error = sec_mdeu_config(csp, &eu, &mode, &hashlen); 138102b553caSRafal Jaworowski if (error) 138202b553caSRafal Jaworowski return (error); 138302b553caSRafal Jaworowski 138402b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_HMAC_SNOOP; 138502b553caSRafal Jaworowski hd->shd_eu_sel1 = eu; 138602b553caSRafal Jaworowski hd->shd_mode1 = mode; 138702b553caSRafal Jaworowski 138802b553caSRafal Jaworowski /* Pointer 0: HMAC Key */ 138902b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, desc->sd_desc_paddr + 1390c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_mkey), csp->csp_auth_klen); 139102b553caSRafal Jaworowski if (error) 139202b553caSRafal Jaworowski return (error); 139302b553caSRafal Jaworowski 139402b553caSRafal Jaworowski /* Pointer 1: HMAC-Only Data IN */ 1395c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 1, crp, crp->crp_aad_start, 1396c0341432SJohn Baldwin crp->crp_aad_length); 139702b553caSRafal Jaworowski if (error) 139802b553caSRafal Jaworowski return (error); 139902b553caSRafal Jaworowski 140002b553caSRafal Jaworowski /* Pointer 2: Cipher Key */ 140102b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr + 1402c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen); 140302b553caSRafal Jaworowski if (error) 140402b553caSRafal Jaworowski return (error); 140502b553caSRafal Jaworowski 140602b553caSRafal Jaworowski /* Pointer 3: IV IN */ 140702b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 3, desc->sd_desc_paddr + 1408c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen); 140902b553caSRafal Jaworowski if (error) 141002b553caSRafal Jaworowski return (error); 141102b553caSRafal Jaworowski 141202b553caSRafal Jaworowski /* Pointer 4: Data IN */ 1413c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start, 1414c0341432SJohn Baldwin crp->crp_payload_length); 141502b553caSRafal Jaworowski if (error) 141602b553caSRafal Jaworowski return (error); 141702b553caSRafal Jaworowski 141802b553caSRafal Jaworowski /* Pointer 5: Data OUT */ 1419c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 5, crp, crp->crp_payload_start, 1420c0341432SJohn Baldwin crp->crp_payload_length); 142102b553caSRafal Jaworowski if (error) 142202b553caSRafal Jaworowski return (error); 142302b553caSRafal Jaworowski 142402b553caSRafal Jaworowski /* Pointer 6: HMAC OUT */ 1425c0341432SJohn Baldwin error = sec_make_pointer_direct(sc, desc, 6, desc->sd_desc_paddr + 1426c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_digest), hashlen); 142702b553caSRafal Jaworowski 142802b553caSRafal Jaworowski return (error); 142902b553caSRafal Jaworowski } 143002b553caSRafal Jaworowski 143102b553caSRafal Jaworowski /* AESU */ 143202b553caSRafal Jaworowski 1433c0341432SJohn Baldwin static bool 1434c0341432SJohn Baldwin sec_aesu_newsession(const struct crypto_session_params *csp) 143502b553caSRafal Jaworowski { 143602b553caSRafal Jaworowski 1437c0341432SJohn Baldwin return (csp->csp_cipher_alg == CRYPTO_AES_CBC); 143802b553caSRafal Jaworowski } 143902b553caSRafal Jaworowski 144002b553caSRafal Jaworowski static int 1441c0341432SJohn Baldwin sec_aesu_make_desc(struct sec_softc *sc, 1442c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc, 1443c0341432SJohn Baldwin struct cryptop *crp) 144402b553caSRafal Jaworowski { 144502b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc; 144602b553caSRafal Jaworowski int error; 144702b553caSRafal Jaworowski 144802b553caSRafal Jaworowski hd->shd_eu_sel0 = SEC_EU_AESU; 144902b553caSRafal Jaworowski hd->shd_mode0 = SEC_AESU_MODE_CBC; 145002b553caSRafal Jaworowski 1451c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { 145202b553caSRafal Jaworowski hd->shd_mode0 |= SEC_AESU_MODE_ED; 145302b553caSRafal Jaworowski hd->shd_dir = 0; 145402b553caSRafal Jaworowski } else 145502b553caSRafal Jaworowski hd->shd_dir = 1; 145602b553caSRafal Jaworowski 1457c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_ETA) 1458c0341432SJohn Baldwin error = sec_build_common_s_desc(sc, desc, csp, crp); 145902b553caSRafal Jaworowski else 1460c0341432SJohn Baldwin error = sec_build_common_ns_desc(sc, desc, csp, crp); 146102b553caSRafal Jaworowski 146202b553caSRafal Jaworowski return (error); 146302b553caSRafal Jaworowski } 146402b553caSRafal Jaworowski 146502b553caSRafal Jaworowski /* MDEU */ 146602b553caSRafal Jaworowski 1467c0341432SJohn Baldwin static bool 146802b553caSRafal Jaworowski sec_mdeu_can_handle(u_int alg) 146902b553caSRafal Jaworowski { 147002b553caSRafal Jaworowski switch (alg) { 147102b553caSRafal Jaworowski case CRYPTO_SHA1: 147202b553caSRafal Jaworowski case CRYPTO_SHA1_HMAC: 147302b553caSRafal Jaworowski case CRYPTO_SHA2_256_HMAC: 147402b553caSRafal Jaworowski case CRYPTO_SHA2_384_HMAC: 147502b553caSRafal Jaworowski case CRYPTO_SHA2_512_HMAC: 1476c0341432SJohn Baldwin return (true); 147702b553caSRafal Jaworowski default: 1478c0341432SJohn Baldwin return (false); 147902b553caSRafal Jaworowski } 148002b553caSRafal Jaworowski } 148102b553caSRafal Jaworowski 148202b553caSRafal Jaworowski static int 1483c0341432SJohn Baldwin sec_mdeu_config(const struct crypto_session_params *csp, u_int *eu, u_int *mode, 1484c0341432SJohn Baldwin u_int *hashlen) 148502b553caSRafal Jaworowski { 148602b553caSRafal Jaworowski 148702b553caSRafal Jaworowski *mode = SEC_MDEU_MODE_PD | SEC_MDEU_MODE_INIT; 148802b553caSRafal Jaworowski *eu = SEC_EU_NONE; 148902b553caSRafal Jaworowski 1490c0341432SJohn Baldwin switch (csp->csp_auth_alg) { 149102b553caSRafal Jaworowski case CRYPTO_SHA1_HMAC: 149202b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC; 149302b553caSRafal Jaworowski /* FALLTHROUGH */ 149402b553caSRafal Jaworowski case CRYPTO_SHA1: 149502b553caSRafal Jaworowski *eu = SEC_EU_MDEU_A; 149602b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_SHA1; 149702b553caSRafal Jaworowski *hashlen = SHA1_HASH_LEN; 149802b553caSRafal Jaworowski break; 149902b553caSRafal Jaworowski case CRYPTO_SHA2_256_HMAC: 150002b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA256; 150102b553caSRafal Jaworowski *eu = SEC_EU_MDEU_A; 150202b553caSRafal Jaworowski break; 150302b553caSRafal Jaworowski case CRYPTO_SHA2_384_HMAC: 150402b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA384; 150502b553caSRafal Jaworowski *eu = SEC_EU_MDEU_B; 150602b553caSRafal Jaworowski break; 150702b553caSRafal Jaworowski case CRYPTO_SHA2_512_HMAC: 150802b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA512; 150902b553caSRafal Jaworowski *eu = SEC_EU_MDEU_B; 151002b553caSRafal Jaworowski break; 151102b553caSRafal Jaworowski default: 151202b553caSRafal Jaworowski return (EINVAL); 151302b553caSRafal Jaworowski } 151402b553caSRafal Jaworowski 151502b553caSRafal Jaworowski if (*mode & SEC_MDEU_MODE_HMAC) 151602b553caSRafal Jaworowski *hashlen = SEC_HMAC_HASH_LEN; 151702b553caSRafal Jaworowski 151802b553caSRafal Jaworowski return (0); 151902b553caSRafal Jaworowski } 152002b553caSRafal Jaworowski 1521c0341432SJohn Baldwin static bool 1522c0341432SJohn Baldwin sec_mdeu_newsession(const struct crypto_session_params *csp) 152302b553caSRafal Jaworowski { 152402b553caSRafal Jaworowski 1525c0341432SJohn Baldwin return (sec_mdeu_can_handle(csp->csp_auth_alg)); 152602b553caSRafal Jaworowski } 152702b553caSRafal Jaworowski 152802b553caSRafal Jaworowski static int 1529c0341432SJohn Baldwin sec_mdeu_make_desc(struct sec_softc *sc, 1530c0341432SJohn Baldwin const struct crypto_session_params *csp, 1531c0341432SJohn Baldwin struct sec_desc *desc, struct cryptop *crp) 153202b553caSRafal Jaworowski { 153302b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc; 153402b553caSRafal Jaworowski u_int eu, mode, hashlen; 153502b553caSRafal Jaworowski int error; 153602b553caSRafal Jaworowski 1537c0341432SJohn Baldwin error = sec_mdeu_config(csp, &eu, &mode, &hashlen); 153802b553caSRafal Jaworowski if (error) 153902b553caSRafal Jaworowski return (error); 154002b553caSRafal Jaworowski 154102b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_COMMON_NONSNOOP; 154202b553caSRafal Jaworowski hd->shd_eu_sel0 = eu; 154302b553caSRafal Jaworowski hd->shd_mode0 = mode; 154402b553caSRafal Jaworowski hd->shd_eu_sel1 = SEC_EU_NONE; 154502b553caSRafal Jaworowski hd->shd_mode1 = 0; 154602b553caSRafal Jaworowski 154702b553caSRafal Jaworowski /* Pointer 0: NULL */ 154802b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, 0, 0); 154902b553caSRafal Jaworowski if (error) 155002b553caSRafal Jaworowski return (error); 155102b553caSRafal Jaworowski 155202b553caSRafal Jaworowski /* Pointer 1: Context In (Not used: NULL) */ 155302b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 1, 0, 0); 155402b553caSRafal Jaworowski if (error) 155502b553caSRafal Jaworowski return (error); 155602b553caSRafal Jaworowski 155702b553caSRafal Jaworowski /* Pointer 2: HMAC Key (or NULL, depending on digest type) */ 155802b553caSRafal Jaworowski if (hd->shd_mode0 & SEC_MDEU_MODE_HMAC) 155902b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, 156002b553caSRafal Jaworowski desc->sd_desc_paddr + offsetof(struct sec_hw_desc, 1561c0341432SJohn Baldwin shd_mkey), csp->csp_auth_klen); 156202b553caSRafal Jaworowski else 156302b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, 0, 0); 156402b553caSRafal Jaworowski 156502b553caSRafal Jaworowski if (error) 156602b553caSRafal Jaworowski return (error); 156702b553caSRafal Jaworowski 156802b553caSRafal Jaworowski /* Pointer 3: Input Data */ 1569c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start, 1570c0341432SJohn Baldwin crp->crp_payload_length); 157102b553caSRafal Jaworowski if (error) 157202b553caSRafal Jaworowski return (error); 157302b553caSRafal Jaworowski 157402b553caSRafal Jaworowski /* Pointer 4: NULL */ 157502b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 4, 0, 0); 157602b553caSRafal Jaworowski if (error) 157702b553caSRafal Jaworowski return (error); 157802b553caSRafal Jaworowski 157902b553caSRafal Jaworowski /* Pointer 5: Hash out */ 1580c0341432SJohn Baldwin error = sec_make_pointer_direct(sc, desc, 5, desc->sd_desc_paddr + 1581c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_digest), hashlen); 158202b553caSRafal Jaworowski if (error) 158302b553caSRafal Jaworowski return (error); 158402b553caSRafal Jaworowski 158502b553caSRafal Jaworowski /* Pointer 6: NULL */ 158602b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 6, 0, 0); 158702b553caSRafal Jaworowski 158802b553caSRafal Jaworowski return (0); 158902b553caSRafal Jaworowski } 1590