102b553caSRafal Jaworowski /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
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/param.h>
3402b553caSRafal Jaworowski #include <sys/systm.h>
3502b553caSRafal Jaworowski #include <sys/bus.h>
3602b553caSRafal Jaworowski #include <sys/endian.h>
3702b553caSRafal Jaworowski #include <sys/kernel.h>
3802b553caSRafal Jaworowski #include <sys/lock.h>
3902b553caSRafal Jaworowski #include <sys/malloc.h>
4002b553caSRafal Jaworowski #include <sys/mbuf.h>
4102b553caSRafal Jaworowski #include <sys/module.h>
4202b553caSRafal Jaworowski #include <sys/mutex.h>
4302b553caSRafal Jaworowski #include <sys/random.h>
4402b553caSRafal Jaworowski #include <sys/rman.h>
4502b553caSRafal Jaworowski
4638f004fbSJustin Hibbits #include <machine/_inttypes.h>
4702b553caSRafal Jaworowski #include <machine/bus.h>
4802b553caSRafal Jaworowski #include <machine/resource.h>
4902b553caSRafal Jaworowski
5002b553caSRafal Jaworowski #include <opencrypto/cryptodev.h>
51c0341432SJohn Baldwin #include <opencrypto/xform_auth.h>
5202b553caSRafal Jaworowski #include "cryptodev_if.h"
5302b553caSRafal Jaworowski
54d1d3233eSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h>
5502b553caSRafal Jaworowski #include <dev/sec/sec.h>
5602b553caSRafal Jaworowski
5702b553caSRafal Jaworowski static int sec_probe(device_t dev);
5802b553caSRafal Jaworowski static int sec_attach(device_t dev);
5902b553caSRafal Jaworowski static int sec_detach(device_t dev);
6002b553caSRafal Jaworowski static int sec_suspend(device_t dev);
6102b553caSRafal Jaworowski static int sec_resume(device_t dev);
62661ee6eeSRafal Jaworowski static int sec_shutdown(device_t dev);
6302b553caSRafal Jaworowski static void sec_primary_intr(void *arg);
6402b553caSRafal Jaworowski static void sec_secondary_intr(void *arg);
6502b553caSRafal Jaworowski static int sec_setup_intr(struct sec_softc *sc, struct resource **ires,
6602b553caSRafal Jaworowski void **ihand, int *irid, driver_intr_t handler, const char *iname);
6702b553caSRafal Jaworowski static void sec_release_intr(struct sec_softc *sc, struct resource *ires,
6802b553caSRafal Jaworowski void *ihand, int irid, const char *iname);
6902b553caSRafal Jaworowski static int sec_controller_reset(struct sec_softc *sc);
7002b553caSRafal Jaworowski static int sec_channel_reset(struct sec_softc *sc, int channel, int full);
7102b553caSRafal Jaworowski static int sec_init(struct sec_softc *sc);
7202b553caSRafal Jaworowski static int sec_alloc_dma_mem(struct sec_softc *sc,
7302b553caSRafal Jaworowski struct sec_dma_mem *dma_mem, bus_size_t size);
7402b553caSRafal Jaworowski static int sec_desc_map_dma(struct sec_softc *sc,
75c0341432SJohn Baldwin struct sec_dma_mem *dma_mem, struct cryptop *crp, bus_size_t size,
7602b553caSRafal Jaworowski struct sec_desc_map_info *sdmi);
7702b553caSRafal Jaworowski static void sec_free_dma_mem(struct sec_dma_mem *dma_mem);
7802b553caSRafal Jaworowski static void sec_enqueue(struct sec_softc *sc);
7902b553caSRafal Jaworowski static int sec_enqueue_desc(struct sec_softc *sc, struct sec_desc *desc,
8002b553caSRafal Jaworowski int channel);
8102b553caSRafal Jaworowski static int sec_eu_channel(struct sec_softc *sc, int eu);
8202b553caSRafal Jaworowski static int sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc,
83c0341432SJohn Baldwin u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize);
8402b553caSRafal Jaworowski static int sec_make_pointer_direct(struct sec_softc *sc,
8502b553caSRafal Jaworowski struct sec_desc *desc, u_int n, bus_addr_t data, bus_size_t dsize);
86c0341432SJohn Baldwin static int sec_probesession(device_t dev,
87c0341432SJohn Baldwin const struct crypto_session_params *csp);
881b0909d5SConrad Meyer static int sec_newsession(device_t dev, crypto_session_t cses,
89c0341432SJohn Baldwin const struct crypto_session_params *csp);
9002b553caSRafal Jaworowski static int sec_process(device_t dev, struct cryptop *crp, int hint);
9102b553caSRafal Jaworowski static int sec_build_common_ns_desc(struct sec_softc *sc,
92c0341432SJohn Baldwin struct sec_desc *desc, const struct crypto_session_params *csp,
93c0341432SJohn Baldwin struct cryptop *crp);
9402b553caSRafal Jaworowski static int sec_build_common_s_desc(struct sec_softc *sc,
95c0341432SJohn Baldwin struct sec_desc *desc, const struct crypto_session_params *csp,
96c0341432SJohn Baldwin struct cryptop *crp);
9702b553caSRafal Jaworowski
9802b553caSRafal Jaworowski static struct sec_desc *sec_find_desc(struct sec_softc *sc, bus_addr_t paddr);
9902b553caSRafal Jaworowski
10002b553caSRafal Jaworowski /* AESU */
101c0341432SJohn Baldwin static bool sec_aesu_newsession(const struct crypto_session_params *csp);
10202b553caSRafal Jaworowski static int sec_aesu_make_desc(struct sec_softc *sc,
103c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc,
104c0341432SJohn Baldwin struct cryptop *crp);
10502b553caSRafal Jaworowski
10602b553caSRafal Jaworowski /* MDEU */
107c0341432SJohn Baldwin static bool sec_mdeu_can_handle(u_int alg);
108c0341432SJohn Baldwin static int sec_mdeu_config(const struct crypto_session_params *csp,
10902b553caSRafal Jaworowski u_int *eu, u_int *mode, u_int *hashlen);
110c0341432SJohn Baldwin static bool sec_mdeu_newsession(const struct crypto_session_params *csp);
11102b553caSRafal Jaworowski static int sec_mdeu_make_desc(struct sec_softc *sc,
112c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc,
113c0341432SJohn Baldwin struct cryptop *crp);
11402b553caSRafal Jaworowski
11502b553caSRafal Jaworowski static device_method_t sec_methods[] = {
11602b553caSRafal Jaworowski /* Device interface */
11702b553caSRafal Jaworowski DEVMETHOD(device_probe, sec_probe),
11802b553caSRafal Jaworowski DEVMETHOD(device_attach, sec_attach),
11902b553caSRafal Jaworowski DEVMETHOD(device_detach, sec_detach),
12002b553caSRafal Jaworowski
12102b553caSRafal Jaworowski DEVMETHOD(device_suspend, sec_suspend),
12202b553caSRafal Jaworowski DEVMETHOD(device_resume, sec_resume),
12302b553caSRafal Jaworowski DEVMETHOD(device_shutdown, sec_shutdown),
12402b553caSRafal Jaworowski
12502b553caSRafal Jaworowski /* Crypto methods */
126c0341432SJohn Baldwin DEVMETHOD(cryptodev_probesession, sec_probesession),
12702b553caSRafal Jaworowski DEVMETHOD(cryptodev_newsession, sec_newsession),
12802b553caSRafal Jaworowski DEVMETHOD(cryptodev_process, sec_process),
12902b553caSRafal Jaworowski
1304b7ec270SMarius Strobl DEVMETHOD_END
13102b553caSRafal Jaworowski };
13202b553caSRafal Jaworowski static driver_t sec_driver = {
13302b553caSRafal Jaworowski "sec",
13402b553caSRafal Jaworowski sec_methods,
13502b553caSRafal Jaworowski sizeof(struct sec_softc),
13602b553caSRafal Jaworowski };
13702b553caSRafal Jaworowski
138bce4876eSJohn Baldwin DRIVER_MODULE(sec, simplebus, sec_driver, 0, 0);
13902b553caSRafal Jaworowski MODULE_DEPEND(sec, crypto, 1, 1, 1);
14002b553caSRafal Jaworowski
14102b553caSRafal Jaworowski static struct sec_eu_methods sec_eus[] = {
14202b553caSRafal Jaworowski {
14302b553caSRafal Jaworowski sec_aesu_newsession,
14402b553caSRafal Jaworowski sec_aesu_make_desc,
14502b553caSRafal Jaworowski },
14602b553caSRafal Jaworowski {
14702b553caSRafal Jaworowski sec_mdeu_newsession,
14802b553caSRafal Jaworowski sec_mdeu_make_desc,
14902b553caSRafal Jaworowski },
15002b553caSRafal Jaworowski { NULL, NULL }
15102b553caSRafal Jaworowski };
15202b553caSRafal Jaworowski
15302b553caSRafal Jaworowski static inline void
sec_sync_dma_mem(struct sec_dma_mem * dma_mem,bus_dmasync_op_t op)15402b553caSRafal Jaworowski sec_sync_dma_mem(struct sec_dma_mem *dma_mem, bus_dmasync_op_t op)
15502b553caSRafal Jaworowski {
15602b553caSRafal Jaworowski
15702b553caSRafal Jaworowski /* Sync only if dma memory is valid */
15802b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL)
15902b553caSRafal Jaworowski bus_dmamap_sync(dma_mem->dma_tag, dma_mem->dma_map, op);
16002b553caSRafal Jaworowski }
16102b553caSRafal Jaworowski
16202b553caSRafal Jaworowski static inline void *
sec_get_pointer_data(struct sec_desc * desc,u_int n)16302b553caSRafal Jaworowski sec_get_pointer_data(struct sec_desc *desc, u_int n)
16402b553caSRafal Jaworowski {
16502b553caSRafal Jaworowski
16602b553caSRafal Jaworowski return (desc->sd_ptr_dmem[n].dma_vaddr);
16702b553caSRafal Jaworowski }
16802b553caSRafal Jaworowski
16902b553caSRafal Jaworowski static int
sec_probe(device_t dev)17002b553caSRafal Jaworowski sec_probe(device_t dev)
17102b553caSRafal Jaworowski {
17202b553caSRafal Jaworowski struct sec_softc *sc;
17302b553caSRafal Jaworowski uint64_t id;
17402b553caSRafal Jaworowski
175add35ed5SIan Lepore if (!ofw_bus_status_okay(dev))
176add35ed5SIan Lepore return (ENXIO);
177add35ed5SIan Lepore
178d1d3233eSRafal Jaworowski if (!ofw_bus_is_compatible(dev, "fsl,sec2.0"))
17902b553caSRafal Jaworowski return (ENXIO);
18002b553caSRafal Jaworowski
18102b553caSRafal Jaworowski sc = device_get_softc(dev);
18202b553caSRafal Jaworowski
18302b553caSRafal Jaworowski sc->sc_rrid = 0;
184d1d3233eSRafal Jaworowski sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
185d1d3233eSRafal Jaworowski RF_ACTIVE);
18602b553caSRafal Jaworowski
18702b553caSRafal Jaworowski if (sc->sc_rres == NULL)
18802b553caSRafal Jaworowski return (ENXIO);
18902b553caSRafal Jaworowski
19002b553caSRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
19102b553caSRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
19202b553caSRafal Jaworowski
19302b553caSRafal Jaworowski id = SEC_READ(sc, SEC_ID);
19402b553caSRafal Jaworowski
19502b553caSRafal Jaworowski bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
19602b553caSRafal Jaworowski
19702b553caSRafal Jaworowski switch (id) {
19802b553caSRafal Jaworowski case SEC_20_ID:
19902b553caSRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 2.0");
20002b553caSRafal Jaworowski sc->sc_version = 2;
20102b553caSRafal Jaworowski break;
20202b553caSRafal Jaworowski case SEC_30_ID:
20302b553caSRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 3.0");
20402b553caSRafal Jaworowski sc->sc_version = 3;
20502b553caSRafal Jaworowski break;
2061aba5158SRafal Jaworowski case SEC_31_ID:
2071aba5158SRafal Jaworowski device_set_desc(dev, "Freescale Security Engine 3.1");
2081aba5158SRafal Jaworowski sc->sc_version = 3;
2091aba5158SRafal Jaworowski break;
21002b553caSRafal Jaworowski default:
2112afca094SJustin Hibbits device_printf(dev, "unknown SEC ID 0x%016"PRIx64"!\n", id);
21202b553caSRafal Jaworowski return (ENXIO);
21302b553caSRafal Jaworowski }
21402b553caSRafal Jaworowski
21502b553caSRafal Jaworowski return (0);
21602b553caSRafal Jaworowski }
21702b553caSRafal Jaworowski
21802b553caSRafal Jaworowski static int
sec_attach(device_t dev)21902b553caSRafal Jaworowski sec_attach(device_t dev)
22002b553caSRafal Jaworowski {
22102b553caSRafal Jaworowski struct sec_softc *sc;
22202b553caSRafal Jaworowski struct sec_hw_lt *lt;
22302b553caSRafal Jaworowski int error = 0;
22402b553caSRafal Jaworowski int i;
22502b553caSRafal Jaworowski
22602b553caSRafal Jaworowski sc = device_get_softc(dev);
22702b553caSRafal Jaworowski sc->sc_dev = dev;
22802b553caSRafal Jaworowski sc->sc_blocked = 0;
22902b553caSRafal Jaworowski sc->sc_shutdown = 0;
23002b553caSRafal Jaworowski
2311b0909d5SConrad Meyer sc->sc_cid = crypto_get_driverid(dev, sizeof(struct sec_session),
2321b0909d5SConrad Meyer CRYPTOCAP_F_HARDWARE);
23302b553caSRafal Jaworowski if (sc->sc_cid < 0) {
23402b553caSRafal Jaworowski device_printf(dev, "could not get crypto driver ID!\n");
23502b553caSRafal Jaworowski return (ENXIO);
23602b553caSRafal Jaworowski }
23702b553caSRafal Jaworowski
23802b553caSRafal Jaworowski /* Init locks */
23902b553caSRafal Jaworowski mtx_init(&sc->sc_controller_lock, device_get_nameunit(dev),
24002b553caSRafal Jaworowski "SEC Controller lock", MTX_DEF);
24102b553caSRafal Jaworowski mtx_init(&sc->sc_descriptors_lock, device_get_nameunit(dev),
24202b553caSRafal Jaworowski "SEC Descriptors lock", MTX_DEF);
24302b553caSRafal Jaworowski
24402b553caSRafal Jaworowski /* Allocate I/O memory for SEC registers */
24502b553caSRafal Jaworowski sc->sc_rrid = 0;
246d1d3233eSRafal Jaworowski sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
247d1d3233eSRafal Jaworowski RF_ACTIVE);
24802b553caSRafal Jaworowski
24902b553caSRafal Jaworowski if (sc->sc_rres == NULL) {
25002b553caSRafal Jaworowski device_printf(dev, "could not allocate I/O memory!\n");
25102b553caSRafal Jaworowski goto fail1;
25202b553caSRafal Jaworowski }
25302b553caSRafal Jaworowski
25402b553caSRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
25502b553caSRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
25602b553caSRafal Jaworowski
25702b553caSRafal Jaworowski /* Setup interrupts */
25802b553caSRafal Jaworowski sc->sc_pri_irid = 0;
25902b553caSRafal Jaworowski error = sec_setup_intr(sc, &sc->sc_pri_ires, &sc->sc_pri_ihand,
26002b553caSRafal Jaworowski &sc->sc_pri_irid, sec_primary_intr, "primary");
26102b553caSRafal Jaworowski
26202b553caSRafal Jaworowski if (error)
26302b553caSRafal Jaworowski goto fail2;
26402b553caSRafal Jaworowski
265d1d3233eSRafal Jaworowski if (sc->sc_version == 3) {
26602b553caSRafal Jaworowski sc->sc_sec_irid = 1;
26702b553caSRafal Jaworowski error = sec_setup_intr(sc, &sc->sc_sec_ires, &sc->sc_sec_ihand,
26802b553caSRafal Jaworowski &sc->sc_sec_irid, sec_secondary_intr, "secondary");
26902b553caSRafal Jaworowski
27002b553caSRafal Jaworowski if (error)
27102b553caSRafal Jaworowski goto fail3;
272d1d3233eSRafal Jaworowski }
27302b553caSRafal Jaworowski
27402b553caSRafal Jaworowski /* Alloc DMA memory for descriptors and link tables */
27502b553caSRafal Jaworowski error = sec_alloc_dma_mem(sc, &(sc->sc_desc_dmem),
27602b553caSRafal Jaworowski SEC_DESCRIPTORS * sizeof(struct sec_hw_desc));
27702b553caSRafal Jaworowski
27802b553caSRafal Jaworowski if (error)
27902b553caSRafal Jaworowski goto fail4;
28002b553caSRafal Jaworowski
28102b553caSRafal Jaworowski error = sec_alloc_dma_mem(sc, &(sc->sc_lt_dmem),
28202b553caSRafal Jaworowski (SEC_LT_ENTRIES + 1) * sizeof(struct sec_hw_lt));
28302b553caSRafal Jaworowski
28402b553caSRafal Jaworowski if (error)
28502b553caSRafal Jaworowski goto fail5;
28602b553caSRafal Jaworowski
28702b553caSRafal Jaworowski /* Fill in descriptors and link tables */
28802b553caSRafal Jaworowski for (i = 0; i < SEC_DESCRIPTORS; i++) {
28902b553caSRafal Jaworowski sc->sc_desc[i].sd_desc =
29002b553caSRafal Jaworowski (struct sec_hw_desc*)(sc->sc_desc_dmem.dma_vaddr) + i;
29102b553caSRafal Jaworowski sc->sc_desc[i].sd_desc_paddr = sc->sc_desc_dmem.dma_paddr +
29202b553caSRafal Jaworowski (i * sizeof(struct sec_hw_desc));
29302b553caSRafal Jaworowski }
29402b553caSRafal Jaworowski
29502b553caSRafal Jaworowski for (i = 0; i < SEC_LT_ENTRIES + 1; i++) {
29602b553caSRafal Jaworowski sc->sc_lt[i].sl_lt =
29702b553caSRafal Jaworowski (struct sec_hw_lt*)(sc->sc_lt_dmem.dma_vaddr) + i;
29802b553caSRafal Jaworowski sc->sc_lt[i].sl_lt_paddr = sc->sc_lt_dmem.dma_paddr +
29902b553caSRafal Jaworowski (i * sizeof(struct sec_hw_lt));
30002b553caSRafal Jaworowski }
30102b553caSRafal Jaworowski
30202b553caSRafal Jaworowski /* Last entry in link table is used to create a circle */
30302b553caSRafal Jaworowski lt = sc->sc_lt[SEC_LT_ENTRIES].sl_lt;
30402b553caSRafal Jaworowski lt->shl_length = 0;
30502b553caSRafal Jaworowski lt->shl_r = 0;
30602b553caSRafal Jaworowski lt->shl_n = 1;
30702b553caSRafal Jaworowski lt->shl_ptr = sc->sc_lt[0].sl_lt_paddr;
30802b553caSRafal Jaworowski
30902b553caSRafal Jaworowski /* Init descriptor and link table queues pointers */
31002b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_free_desc_get_cnt, SEC_DESCRIPTORS);
31102b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_free_desc_put_cnt, SEC_DESCRIPTORS);
31202b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_ready_desc_get_cnt, SEC_DESCRIPTORS);
31302b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_ready_desc_put_cnt, SEC_DESCRIPTORS);
31402b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_queued_desc_get_cnt, SEC_DESCRIPTORS);
31502b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_queued_desc_put_cnt, SEC_DESCRIPTORS);
31602b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_lt_alloc_cnt, SEC_LT_ENTRIES);
31702b553caSRafal Jaworowski SEC_CNT_INIT(sc, sc_lt_free_cnt, SEC_LT_ENTRIES);
31802b553caSRafal Jaworowski
31902b553caSRafal Jaworowski /* Create masks for fast checks */
32002b553caSRafal Jaworowski sc->sc_int_error_mask = 0;
32102b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++)
32202b553caSRafal Jaworowski sc->sc_int_error_mask |= (~0ULL & SEC_INT_CH_ERR(i));
32302b553caSRafal Jaworowski
32402b553caSRafal Jaworowski switch (sc->sc_version) {
32502b553caSRafal Jaworowski case 2:
32602b553caSRafal Jaworowski sc->sc_channel_idle_mask =
32702b553caSRafal Jaworowski (SEC_CHAN_CSR2_FFLVL_M << SEC_CHAN_CSR2_FFLVL_S) |
32802b553caSRafal Jaworowski (SEC_CHAN_CSR2_MSTATE_M << SEC_CHAN_CSR2_MSTATE_S) |
32902b553caSRafal Jaworowski (SEC_CHAN_CSR2_PSTATE_M << SEC_CHAN_CSR2_PSTATE_S) |
33002b553caSRafal Jaworowski (SEC_CHAN_CSR2_GSTATE_M << SEC_CHAN_CSR2_GSTATE_S);
33102b553caSRafal Jaworowski break;
33202b553caSRafal Jaworowski case 3:
33302b553caSRafal Jaworowski sc->sc_channel_idle_mask =
33402b553caSRafal Jaworowski (SEC_CHAN_CSR3_FFLVL_M << SEC_CHAN_CSR3_FFLVL_S) |
33502b553caSRafal Jaworowski (SEC_CHAN_CSR3_MSTATE_M << SEC_CHAN_CSR3_MSTATE_S) |
33602b553caSRafal Jaworowski (SEC_CHAN_CSR3_PSTATE_M << SEC_CHAN_CSR3_PSTATE_S) |
33702b553caSRafal Jaworowski (SEC_CHAN_CSR3_GSTATE_M << SEC_CHAN_CSR3_GSTATE_S);
33802b553caSRafal Jaworowski break;
33902b553caSRafal Jaworowski }
34002b553caSRafal Jaworowski
34102b553caSRafal Jaworowski /* Init hardware */
34202b553caSRafal Jaworowski error = sec_init(sc);
34302b553caSRafal Jaworowski
34402b553caSRafal Jaworowski if (error)
34502b553caSRafal Jaworowski goto fail6;
34602b553caSRafal Jaworowski
34702b553caSRafal Jaworowski return (0);
34802b553caSRafal Jaworowski
34902b553caSRafal Jaworowski fail6:
35002b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_lt_dmem));
35102b553caSRafal Jaworowski fail5:
35202b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_desc_dmem));
35302b553caSRafal Jaworowski fail4:
35402b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_sec_ires, sc->sc_sec_ihand,
35502b553caSRafal Jaworowski sc->sc_sec_irid, "secondary");
35602b553caSRafal Jaworowski fail3:
35702b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_pri_ires, sc->sc_pri_ihand,
35802b553caSRafal Jaworowski sc->sc_pri_irid, "primary");
35902b553caSRafal Jaworowski fail2:
36002b553caSRafal Jaworowski bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
36102b553caSRafal Jaworowski fail1:
36202b553caSRafal Jaworowski mtx_destroy(&sc->sc_controller_lock);
36302b553caSRafal Jaworowski mtx_destroy(&sc->sc_descriptors_lock);
36402b553caSRafal Jaworowski
36502b553caSRafal Jaworowski return (ENXIO);
36602b553caSRafal Jaworowski }
36702b553caSRafal Jaworowski
36802b553caSRafal Jaworowski static int
sec_detach(device_t dev)36902b553caSRafal Jaworowski sec_detach(device_t dev)
37002b553caSRafal Jaworowski {
37102b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev);
37202b553caSRafal Jaworowski int i, error, timeout = SEC_TIMEOUT;
37302b553caSRafal Jaworowski
37402b553caSRafal Jaworowski /* Prepare driver to shutdown */
37502b553caSRafal Jaworowski SEC_LOCK(sc, descriptors);
37602b553caSRafal Jaworowski sc->sc_shutdown = 1;
37702b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
37802b553caSRafal Jaworowski
37902b553caSRafal Jaworowski /* Wait until all queued processing finishes */
38002b553caSRafal Jaworowski while (1) {
38102b553caSRafal Jaworowski SEC_LOCK(sc, descriptors);
38202b553caSRafal Jaworowski i = SEC_READY_DESC_CNT(sc) + SEC_QUEUED_DESC_CNT(sc);
38302b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
38402b553caSRafal Jaworowski
38502b553caSRafal Jaworowski if (i == 0)
38602b553caSRafal Jaworowski break;
38702b553caSRafal Jaworowski
38802b553caSRafal Jaworowski if (timeout < 0) {
38902b553caSRafal Jaworowski device_printf(dev, "queue flush timeout!\n");
39002b553caSRafal Jaworowski
39102b553caSRafal Jaworowski /* DMA can be still active - stop it */
39202b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++)
39302b553caSRafal Jaworowski sec_channel_reset(sc, i, 1);
39402b553caSRafal Jaworowski
39502b553caSRafal Jaworowski break;
39602b553caSRafal Jaworowski }
39702b553caSRafal Jaworowski
39802b553caSRafal Jaworowski timeout -= 1000;
39902b553caSRafal Jaworowski DELAY(1000);
40002b553caSRafal Jaworowski }
40102b553caSRafal Jaworowski
40202b553caSRafal Jaworowski /* Disable interrupts */
40302b553caSRafal Jaworowski SEC_WRITE(sc, SEC_IER, 0);
40402b553caSRafal Jaworowski
40502b553caSRafal Jaworowski /* Unregister from OCF */
40602b553caSRafal Jaworowski crypto_unregister_all(sc->sc_cid);
40702b553caSRafal Jaworowski
40802b553caSRafal Jaworowski /* Free DMA memory */
40902b553caSRafal Jaworowski for (i = 0; i < SEC_DESCRIPTORS; i++)
41002b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(&(sc->sc_desc[i]));
41102b553caSRafal Jaworowski
41202b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_lt_dmem));
41302b553caSRafal Jaworowski sec_free_dma_mem(&(sc->sc_desc_dmem));
41402b553caSRafal Jaworowski
41502b553caSRafal Jaworowski /* Release interrupts */
41602b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_pri_ires, sc->sc_pri_ihand,
41702b553caSRafal Jaworowski sc->sc_pri_irid, "primary");
41802b553caSRafal Jaworowski sec_release_intr(sc, sc->sc_sec_ires, sc->sc_sec_ihand,
41902b553caSRafal Jaworowski sc->sc_sec_irid, "secondary");
42002b553caSRafal Jaworowski
42102b553caSRafal Jaworowski /* Release memory */
42202b553caSRafal Jaworowski if (sc->sc_rres) {
42302b553caSRafal Jaworowski error = bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid,
42402b553caSRafal Jaworowski sc->sc_rres);
42502b553caSRafal Jaworowski if (error)
42602b553caSRafal Jaworowski device_printf(dev, "bus_release_resource() failed for"
42702b553caSRafal Jaworowski " I/O memory, error %d\n", error);
42802b553caSRafal Jaworowski
42902b553caSRafal Jaworowski sc->sc_rres = NULL;
43002b553caSRafal Jaworowski }
43102b553caSRafal Jaworowski
43202b553caSRafal Jaworowski mtx_destroy(&sc->sc_controller_lock);
43302b553caSRafal Jaworowski mtx_destroy(&sc->sc_descriptors_lock);
43402b553caSRafal Jaworowski
43502b553caSRafal Jaworowski return (0);
43602b553caSRafal Jaworowski }
43702b553caSRafal Jaworowski
43802b553caSRafal Jaworowski static int
sec_suspend(device_t dev)43902b553caSRafal Jaworowski sec_suspend(device_t dev)
44002b553caSRafal Jaworowski {
44102b553caSRafal Jaworowski
44202b553caSRafal Jaworowski return (0);
44302b553caSRafal Jaworowski }
44402b553caSRafal Jaworowski
44502b553caSRafal Jaworowski static int
sec_resume(device_t dev)44602b553caSRafal Jaworowski sec_resume(device_t dev)
44702b553caSRafal Jaworowski {
44802b553caSRafal Jaworowski
44902b553caSRafal Jaworowski return (0);
45002b553caSRafal Jaworowski }
45102b553caSRafal Jaworowski
452661ee6eeSRafal Jaworowski static int
sec_shutdown(device_t dev)45302b553caSRafal Jaworowski sec_shutdown(device_t dev)
45402b553caSRafal Jaworowski {
455661ee6eeSRafal Jaworowski
456661ee6eeSRafal Jaworowski return (0);
45702b553caSRafal Jaworowski }
45802b553caSRafal Jaworowski
45902b553caSRafal Jaworowski static int
sec_setup_intr(struct sec_softc * sc,struct resource ** ires,void ** ihand,int * irid,driver_intr_t handler,const char * iname)46002b553caSRafal Jaworowski sec_setup_intr(struct sec_softc *sc, struct resource **ires, void **ihand,
46102b553caSRafal Jaworowski int *irid, driver_intr_t handler, const char *iname)
46202b553caSRafal Jaworowski {
46302b553caSRafal Jaworowski int error;
46402b553caSRafal Jaworowski
46502b553caSRafal Jaworowski (*ires) = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, irid,
46602b553caSRafal Jaworowski RF_ACTIVE);
46702b553caSRafal Jaworowski
46802b553caSRafal Jaworowski if ((*ires) == NULL) {
46902b553caSRafal Jaworowski device_printf(sc->sc_dev, "could not allocate %s IRQ\n", iname);
47002b553caSRafal Jaworowski return (ENXIO);
47102b553caSRafal Jaworowski }
47202b553caSRafal Jaworowski
47302b553caSRafal Jaworowski error = bus_setup_intr(sc->sc_dev, *ires, INTR_MPSAFE | INTR_TYPE_NET,
47402b553caSRafal Jaworowski NULL, handler, sc, ihand);
47502b553caSRafal Jaworowski
47602b553caSRafal Jaworowski if (error) {
47702b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to set up %s IRQ\n", iname);
47802b553caSRafal Jaworowski if (bus_release_resource(sc->sc_dev, SYS_RES_IRQ, *irid, *ires))
47902b553caSRafal Jaworowski device_printf(sc->sc_dev, "could not release %s IRQ\n",
48002b553caSRafal Jaworowski iname);
48102b553caSRafal Jaworowski
48202b553caSRafal Jaworowski (*ires) = NULL;
48302b553caSRafal Jaworowski return (error);
48402b553caSRafal Jaworowski }
48502b553caSRafal Jaworowski
48602b553caSRafal Jaworowski return (0);
48702b553caSRafal Jaworowski }
48802b553caSRafal Jaworowski
48902b553caSRafal Jaworowski static void
sec_release_intr(struct sec_softc * sc,struct resource * ires,void * ihand,int irid,const char * iname)49002b553caSRafal Jaworowski sec_release_intr(struct sec_softc *sc, struct resource *ires, void *ihand,
49102b553caSRafal Jaworowski int irid, const char *iname)
49202b553caSRafal Jaworowski {
49302b553caSRafal Jaworowski int error;
49402b553caSRafal Jaworowski
49502b553caSRafal Jaworowski if (ires == NULL)
49602b553caSRafal Jaworowski return;
49702b553caSRafal Jaworowski
49802b553caSRafal Jaworowski error = bus_teardown_intr(sc->sc_dev, ires, ihand);
49902b553caSRafal Jaworowski if (error)
50002b553caSRafal Jaworowski device_printf(sc->sc_dev, "bus_teardown_intr() failed for %s"
50102b553caSRafal Jaworowski " IRQ, error %d\n", iname, error);
50202b553caSRafal Jaworowski
50302b553caSRafal Jaworowski error = bus_release_resource(sc->sc_dev, SYS_RES_IRQ, irid, ires);
50402b553caSRafal Jaworowski if (error)
50502b553caSRafal Jaworowski device_printf(sc->sc_dev, "bus_release_resource() failed for %s"
50602b553caSRafal Jaworowski " IRQ, error %d\n", iname, error);
50702b553caSRafal Jaworowski }
50802b553caSRafal Jaworowski
50902b553caSRafal Jaworowski static void
sec_primary_intr(void * arg)51002b553caSRafal Jaworowski sec_primary_intr(void *arg)
51102b553caSRafal Jaworowski {
512c0341432SJohn Baldwin struct sec_session *ses;
51302b553caSRafal Jaworowski struct sec_softc *sc = arg;
51402b553caSRafal Jaworowski struct sec_desc *desc;
515c0341432SJohn Baldwin struct cryptop *crp;
51602b553caSRafal Jaworowski uint64_t isr;
517c0341432SJohn Baldwin uint8_t hash[HASH_MAX_LEN];
51802b553caSRafal Jaworowski int i, wakeup = 0;
51902b553caSRafal Jaworowski
52002b553caSRafal Jaworowski SEC_LOCK(sc, controller);
52102b553caSRafal Jaworowski
52202b553caSRafal Jaworowski /* Check for errors */
52302b553caSRafal Jaworowski isr = SEC_READ(sc, SEC_ISR);
52402b553caSRafal Jaworowski if (isr & sc->sc_int_error_mask) {
52502b553caSRafal Jaworowski /* Check each channel for error */
52602b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) {
52702b553caSRafal Jaworowski if ((isr & SEC_INT_CH_ERR(i)) == 0)
52802b553caSRafal Jaworowski continue;
52902b553caSRafal Jaworowski
53002b553caSRafal Jaworowski device_printf(sc->sc_dev,
53102b553caSRafal Jaworowski "I/O error on channel %i!\n", i);
53202b553caSRafal Jaworowski
53302b553caSRafal Jaworowski /* Find and mark problematic descriptor */
53402b553caSRafal Jaworowski desc = sec_find_desc(sc, SEC_READ(sc,
53502b553caSRafal Jaworowski SEC_CHAN_CDPR(i)));
53602b553caSRafal Jaworowski
53702b553caSRafal Jaworowski if (desc != NULL)
53802b553caSRafal Jaworowski desc->sd_error = EIO;
53902b553caSRafal Jaworowski
54002b553caSRafal Jaworowski /* Do partial channel reset */
54102b553caSRafal Jaworowski sec_channel_reset(sc, i, 0);
54202b553caSRafal Jaworowski }
54302b553caSRafal Jaworowski }
54402b553caSRafal Jaworowski
54502b553caSRafal Jaworowski /* ACK interrupt */
54602b553caSRafal Jaworowski SEC_WRITE(sc, SEC_ICR, 0xFFFFFFFFFFFFFFFFULL);
54702b553caSRafal Jaworowski
54802b553caSRafal Jaworowski SEC_UNLOCK(sc, controller);
54902b553caSRafal Jaworowski SEC_LOCK(sc, descriptors);
55002b553caSRafal Jaworowski
55102b553caSRafal Jaworowski /* Handle processed descriptors */
55202b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
55302b553caSRafal Jaworowski
55402b553caSRafal Jaworowski while (SEC_QUEUED_DESC_CNT(sc) > 0) {
55502b553caSRafal Jaworowski desc = SEC_GET_QUEUED_DESC(sc);
55602b553caSRafal Jaworowski
55702b553caSRafal Jaworowski if (desc->sd_desc->shd_done != 0xFF && desc->sd_error == 0) {
55802b553caSRafal Jaworowski SEC_PUT_BACK_QUEUED_DESC(sc);
55902b553caSRafal Jaworowski break;
56002b553caSRafal Jaworowski }
56102b553caSRafal Jaworowski
56202b553caSRafal Jaworowski SEC_DESC_SYNC_POINTERS(desc, BUS_DMASYNC_PREREAD |
56302b553caSRafal Jaworowski BUS_DMASYNC_PREWRITE);
56402b553caSRafal Jaworowski
565c0341432SJohn Baldwin crp = desc->sd_crp;
566c0341432SJohn Baldwin crp->crp_etype = desc->sd_error;
567c0341432SJohn Baldwin if (crp->crp_etype == 0) {
568c0341432SJohn Baldwin ses = crypto_get_driver_session(crp->crp_session);
569c0341432SJohn Baldwin if (ses->ss_mlen != 0) {
570c0341432SJohn Baldwin if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
571c0341432SJohn Baldwin crypto_copydata(crp,
572c0341432SJohn Baldwin crp->crp_digest_start,
573c0341432SJohn Baldwin ses->ss_mlen, hash);
574c0341432SJohn Baldwin if (timingsafe_bcmp(
575c0341432SJohn Baldwin desc->sd_desc->shd_digest,
576c0341432SJohn Baldwin hash, ses->ss_mlen) != 0)
577c0341432SJohn Baldwin crp->crp_etype = EBADMSG;
578c0341432SJohn Baldwin } else
579c0341432SJohn Baldwin crypto_copyback(crp,
580c0341432SJohn Baldwin crp->crp_digest_start,
581c0341432SJohn Baldwin ses->ss_mlen,
582c0341432SJohn Baldwin desc->sd_desc->shd_digest);
583c0341432SJohn Baldwin }
584c0341432SJohn Baldwin }
58502b553caSRafal Jaworowski crypto_done(desc->sd_crp);
58602b553caSRafal Jaworowski
58702b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(desc);
58802b553caSRafal Jaworowski SEC_DESC_FREE_LT(sc, desc);
58902b553caSRafal Jaworowski SEC_DESC_QUEUED2FREE(sc);
59002b553caSRafal Jaworowski }
59102b553caSRafal Jaworowski
59202b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
59302b553caSRafal Jaworowski
59402b553caSRafal Jaworowski if (!sc->sc_shutdown) {
59502b553caSRafal Jaworowski wakeup = sc->sc_blocked;
59602b553caSRafal Jaworowski sc->sc_blocked = 0;
59702b553caSRafal Jaworowski }
59802b553caSRafal Jaworowski
59902b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
60002b553caSRafal Jaworowski
60102b553caSRafal Jaworowski /* Enqueue ready descriptors in hardware */
60202b553caSRafal Jaworowski sec_enqueue(sc);
60302b553caSRafal Jaworowski
60402b553caSRafal Jaworowski if (wakeup)
60502b553caSRafal Jaworowski crypto_unblock(sc->sc_cid, wakeup);
60602b553caSRafal Jaworowski }
60702b553caSRafal Jaworowski
60802b553caSRafal Jaworowski static void
sec_secondary_intr(void * arg)60902b553caSRafal Jaworowski sec_secondary_intr(void *arg)
61002b553caSRafal Jaworowski {
61102b553caSRafal Jaworowski struct sec_softc *sc = arg;
61202b553caSRafal Jaworowski
61302b553caSRafal Jaworowski device_printf(sc->sc_dev, "spurious secondary interrupt!\n");
61402b553caSRafal Jaworowski sec_primary_intr(arg);
61502b553caSRafal Jaworowski }
61602b553caSRafal Jaworowski
61702b553caSRafal Jaworowski static int
sec_controller_reset(struct sec_softc * sc)61802b553caSRafal Jaworowski sec_controller_reset(struct sec_softc *sc)
61902b553caSRafal Jaworowski {
62002b553caSRafal Jaworowski int timeout = SEC_TIMEOUT;
62102b553caSRafal Jaworowski
62202b553caSRafal Jaworowski /* Reset Controller */
62302b553caSRafal Jaworowski SEC_WRITE(sc, SEC_MCR, SEC_MCR_SWR);
62402b553caSRafal Jaworowski
62502b553caSRafal Jaworowski while (SEC_READ(sc, SEC_MCR) & SEC_MCR_SWR) {
62602b553caSRafal Jaworowski DELAY(1000);
62702b553caSRafal Jaworowski timeout -= 1000;
62802b553caSRafal Jaworowski
62902b553caSRafal Jaworowski if (timeout < 0) {
63002b553caSRafal Jaworowski device_printf(sc->sc_dev, "timeout while waiting for "
63102b553caSRafal Jaworowski "device reset!\n");
63202b553caSRafal Jaworowski return (ETIMEDOUT);
63302b553caSRafal Jaworowski }
63402b553caSRafal Jaworowski }
63502b553caSRafal Jaworowski
63602b553caSRafal Jaworowski return (0);
63702b553caSRafal Jaworowski }
63802b553caSRafal Jaworowski
63902b553caSRafal Jaworowski static int
sec_channel_reset(struct sec_softc * sc,int channel,int full)64002b553caSRafal Jaworowski sec_channel_reset(struct sec_softc *sc, int channel, int full)
64102b553caSRafal Jaworowski {
64202b553caSRafal Jaworowski int timeout = SEC_TIMEOUT;
64302b553caSRafal Jaworowski uint64_t bit = (full) ? SEC_CHAN_CCR_R : SEC_CHAN_CCR_CON;
64402b553caSRafal Jaworowski uint64_t reg;
64502b553caSRafal Jaworowski
64602b553caSRafal Jaworowski /* Reset Channel */
64702b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CCR(channel));
64802b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_CCR(channel), reg | bit);
64902b553caSRafal Jaworowski
65002b553caSRafal Jaworowski while (SEC_READ(sc, SEC_CHAN_CCR(channel)) & bit) {
65102b553caSRafal Jaworowski DELAY(1000);
65202b553caSRafal Jaworowski timeout -= 1000;
65302b553caSRafal Jaworowski
65402b553caSRafal Jaworowski if (timeout < 0) {
65502b553caSRafal Jaworowski device_printf(sc->sc_dev, "timeout while waiting for "
65602b553caSRafal Jaworowski "channel reset!\n");
65702b553caSRafal Jaworowski return (ETIMEDOUT);
65802b553caSRafal Jaworowski }
65902b553caSRafal Jaworowski }
66002b553caSRafal Jaworowski
66102b553caSRafal Jaworowski if (full) {
66202b553caSRafal Jaworowski reg = SEC_CHAN_CCR_CDIE | SEC_CHAN_CCR_NT | SEC_CHAN_CCR_BS;
66302b553caSRafal Jaworowski
66402b553caSRafal Jaworowski switch(sc->sc_version) {
66502b553caSRafal Jaworowski case 2:
66602b553caSRafal Jaworowski reg |= SEC_CHAN_CCR_CDWE;
66702b553caSRafal Jaworowski break;
66802b553caSRafal Jaworowski case 3:
66902b553caSRafal Jaworowski reg |= SEC_CHAN_CCR_AWSE | SEC_CHAN_CCR_WGN;
67002b553caSRafal Jaworowski break;
67102b553caSRafal Jaworowski }
67202b553caSRafal Jaworowski
67302b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_CCR(channel), reg);
67402b553caSRafal Jaworowski }
67502b553caSRafal Jaworowski
67602b553caSRafal Jaworowski return (0);
67702b553caSRafal Jaworowski }
67802b553caSRafal Jaworowski
67902b553caSRafal Jaworowski static int
sec_init(struct sec_softc * sc)68002b553caSRafal Jaworowski sec_init(struct sec_softc *sc)
68102b553caSRafal Jaworowski {
68202b553caSRafal Jaworowski uint64_t reg;
68302b553caSRafal Jaworowski int error, i;
68402b553caSRafal Jaworowski
68502b553caSRafal Jaworowski /* Reset controller twice to clear all pending interrupts */
68602b553caSRafal Jaworowski error = sec_controller_reset(sc);
68702b553caSRafal Jaworowski if (error)
68802b553caSRafal Jaworowski return (error);
68902b553caSRafal Jaworowski
69002b553caSRafal Jaworowski error = sec_controller_reset(sc);
69102b553caSRafal Jaworowski if (error)
69202b553caSRafal Jaworowski return (error);
69302b553caSRafal Jaworowski
69402b553caSRafal Jaworowski /* Reset channels */
69502b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) {
69602b553caSRafal Jaworowski error = sec_channel_reset(sc, i, 1);
69702b553caSRafal Jaworowski if (error)
69802b553caSRafal Jaworowski return (error);
69902b553caSRafal Jaworowski }
70002b553caSRafal Jaworowski
70102b553caSRafal Jaworowski /* Enable Interrupts */
70202b553caSRafal Jaworowski reg = SEC_INT_ITO;
70302b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++)
70402b553caSRafal Jaworowski reg |= SEC_INT_CH_DN(i) | SEC_INT_CH_ERR(i);
70502b553caSRafal Jaworowski
70602b553caSRafal Jaworowski SEC_WRITE(sc, SEC_IER, reg);
70702b553caSRafal Jaworowski
70802b553caSRafal Jaworowski return (error);
70902b553caSRafal Jaworowski }
71002b553caSRafal Jaworowski
71102b553caSRafal Jaworowski static void
sec_alloc_dma_mem_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error)71202b553caSRafal Jaworowski sec_alloc_dma_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
71302b553caSRafal Jaworowski {
71402b553caSRafal Jaworowski struct sec_dma_mem *dma_mem = arg;
71502b553caSRafal Jaworowski
71602b553caSRafal Jaworowski if (error)
71702b553caSRafal Jaworowski return;
71802b553caSRafal Jaworowski
71902b553caSRafal Jaworowski KASSERT(nseg == 1, ("Wrong number of segments, should be 1"));
72002b553caSRafal Jaworowski dma_mem->dma_paddr = segs->ds_addr;
72102b553caSRafal Jaworowski }
72202b553caSRafal Jaworowski
72302b553caSRafal Jaworowski static void
sec_dma_map_desc_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error)72402b553caSRafal Jaworowski sec_dma_map_desc_cb(void *arg, bus_dma_segment_t *segs, int nseg,
72502b553caSRafal Jaworowski int error)
72602b553caSRafal Jaworowski {
72702b553caSRafal Jaworowski struct sec_desc_map_info *sdmi = arg;
72802b553caSRafal Jaworowski struct sec_softc *sc = sdmi->sdmi_sc;
72902b553caSRafal Jaworowski struct sec_lt *lt = NULL;
73002b553caSRafal Jaworowski bus_addr_t addr;
73102b553caSRafal Jaworowski bus_size_t size;
73202b553caSRafal Jaworowski int i;
73302b553caSRafal Jaworowski
73402b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors);
73502b553caSRafal Jaworowski
73602b553caSRafal Jaworowski if (error)
73702b553caSRafal Jaworowski return;
73802b553caSRafal Jaworowski
73902b553caSRafal Jaworowski for (i = 0; i < nseg; i++) {
74002b553caSRafal Jaworowski addr = segs[i].ds_addr;
74102b553caSRafal Jaworowski size = segs[i].ds_len;
74202b553caSRafal Jaworowski
74302b553caSRafal Jaworowski /* Skip requested offset */
74402b553caSRafal Jaworowski if (sdmi->sdmi_offset >= size) {
74502b553caSRafal Jaworowski sdmi->sdmi_offset -= size;
74602b553caSRafal Jaworowski continue;
74702b553caSRafal Jaworowski }
74802b553caSRafal Jaworowski
74902b553caSRafal Jaworowski addr += sdmi->sdmi_offset;
75002b553caSRafal Jaworowski size -= sdmi->sdmi_offset;
75102b553caSRafal Jaworowski sdmi->sdmi_offset = 0;
75202b553caSRafal Jaworowski
75302b553caSRafal Jaworowski /* Do not link more than requested */
75402b553caSRafal Jaworowski if (sdmi->sdmi_size < size)
75502b553caSRafal Jaworowski size = sdmi->sdmi_size;
75602b553caSRafal Jaworowski
75702b553caSRafal Jaworowski lt = SEC_ALLOC_LT_ENTRY(sc);
75802b553caSRafal Jaworowski lt->sl_lt->shl_length = size;
75902b553caSRafal Jaworowski lt->sl_lt->shl_r = 0;
76002b553caSRafal Jaworowski lt->sl_lt->shl_n = 0;
76102b553caSRafal Jaworowski lt->sl_lt->shl_ptr = addr;
76202b553caSRafal Jaworowski
76302b553caSRafal Jaworowski if (sdmi->sdmi_lt_first == NULL)
76402b553caSRafal Jaworowski sdmi->sdmi_lt_first = lt;
76502b553caSRafal Jaworowski
76602b553caSRafal Jaworowski sdmi->sdmi_lt_used += 1;
76702b553caSRafal Jaworowski
76802b553caSRafal Jaworowski if ((sdmi->sdmi_size -= size) == 0)
76902b553caSRafal Jaworowski break;
77002b553caSRafal Jaworowski }
77102b553caSRafal Jaworowski
77202b553caSRafal Jaworowski sdmi->sdmi_lt_last = lt;
77302b553caSRafal Jaworowski }
77402b553caSRafal Jaworowski
77502b553caSRafal Jaworowski static int
sec_alloc_dma_mem(struct sec_softc * sc,struct sec_dma_mem * dma_mem,bus_size_t size)77602b553caSRafal Jaworowski sec_alloc_dma_mem(struct sec_softc *sc, struct sec_dma_mem *dma_mem,
77702b553caSRafal Jaworowski bus_size_t size)
77802b553caSRafal Jaworowski {
77902b553caSRafal Jaworowski int error;
78002b553caSRafal Jaworowski
78102b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL)
78202b553caSRafal Jaworowski return (EBUSY);
78302b553caSRafal Jaworowski
78402b553caSRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */
78502b553caSRafal Jaworowski SEC_DMA_ALIGNMENT, 0, /* alignment, boundary */
78602b553caSRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
78702b553caSRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */
78802b553caSRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */
78902b553caSRafal Jaworowski size, 1, /* maxsize, nsegments */
79002b553caSRafal Jaworowski size, 0, /* maxsegsz, flags */
79102b553caSRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */
79202b553caSRafal Jaworowski &(dma_mem->dma_tag)); /* dmat */
79302b553caSRafal Jaworowski
79402b553caSRafal Jaworowski if (error) {
79502b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate busdma tag, error"
79602b553caSRafal Jaworowski " %i!\n", error);
79702b553caSRafal Jaworowski goto err1;
79802b553caSRafal Jaworowski }
79902b553caSRafal Jaworowski
80002b553caSRafal Jaworowski error = bus_dmamem_alloc(dma_mem->dma_tag, &(dma_mem->dma_vaddr),
80102b553caSRafal Jaworowski BUS_DMA_NOWAIT | BUS_DMA_ZERO, &(dma_mem->dma_map));
80202b553caSRafal Jaworowski
80302b553caSRafal Jaworowski if (error) {
80402b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate DMA safe"
80502b553caSRafal Jaworowski " memory, error %i!\n", error);
80602b553caSRafal Jaworowski goto err2;
80702b553caSRafal Jaworowski }
80802b553caSRafal Jaworowski
80902b553caSRafal Jaworowski error = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map,
81002b553caSRafal Jaworowski dma_mem->dma_vaddr, size, sec_alloc_dma_mem_cb, dma_mem,
81102b553caSRafal Jaworowski BUS_DMA_NOWAIT);
81202b553caSRafal Jaworowski
81302b553caSRafal Jaworowski if (error) {
81402b553caSRafal Jaworowski device_printf(sc->sc_dev, "cannot get address of the DMA"
81502b553caSRafal Jaworowski " memory, error %i\n", error);
81602b553caSRafal Jaworowski goto err3;
81702b553caSRafal Jaworowski }
81802b553caSRafal Jaworowski
81902b553caSRafal Jaworowski dma_mem->dma_is_map = 0;
82002b553caSRafal Jaworowski return (0);
82102b553caSRafal Jaworowski
82202b553caSRafal Jaworowski err3:
82302b553caSRafal Jaworowski bus_dmamem_free(dma_mem->dma_tag, dma_mem->dma_vaddr, dma_mem->dma_map);
82402b553caSRafal Jaworowski err2:
82502b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag);
82602b553caSRafal Jaworowski err1:
82702b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL;
82802b553caSRafal Jaworowski return(error);
82902b553caSRafal Jaworowski }
83002b553caSRafal Jaworowski
83102b553caSRafal Jaworowski static int
sec_desc_map_dma(struct sec_softc * sc,struct sec_dma_mem * dma_mem,struct cryptop * crp,bus_size_t size,struct sec_desc_map_info * sdmi)832c0341432SJohn Baldwin sec_desc_map_dma(struct sec_softc *sc, struct sec_dma_mem *dma_mem,
833c0341432SJohn Baldwin struct cryptop *crp, bus_size_t size, struct sec_desc_map_info *sdmi)
83402b553caSRafal Jaworowski {
83502b553caSRafal Jaworowski int error;
83602b553caSRafal Jaworowski
83702b553caSRafal Jaworowski if (dma_mem->dma_vaddr != NULL)
83802b553caSRafal Jaworowski return (EBUSY);
83902b553caSRafal Jaworowski
840b02676a2SJohn Baldwin switch (crp->crp_buf.cb_type) {
841c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG:
84202b553caSRafal Jaworowski break;
843c0341432SJohn Baldwin case CRYPTO_BUF_UIO:
84402b553caSRafal Jaworowski size = SEC_FREE_LT_CNT(sc) * SEC_MAX_DMA_BLOCK_SIZE;
84502b553caSRafal Jaworowski break;
846c0341432SJohn Baldwin case CRYPTO_BUF_MBUF:
847b02676a2SJohn Baldwin size = m_length(crp->crp_buf.cb_mbuf, NULL);
84802b553caSRafal Jaworowski break;
849883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF:
850883a0196SJohn Baldwin size = crp->crp_buf.cb_mbuf->m_len;
851883a0196SJohn Baldwin break;
852e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE:
8532941010bSBrandon Bergren size = PAGE_SIZE - crp->crp_buf.cb_vm_page_offset;
854e6f6d0c9SAlan Somers break;
85502b553caSRafal Jaworowski default:
85602b553caSRafal Jaworowski return (EINVAL);
85702b553caSRafal Jaworowski }
85802b553caSRafal Jaworowski
85902b553caSRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */
86002b553caSRafal Jaworowski SEC_DMA_ALIGNMENT, 0, /* alignment, boundary */
86102b553caSRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
86202b553caSRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */
86302b553caSRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */
86402b553caSRafal Jaworowski size, /* maxsize */
86502b553caSRafal Jaworowski SEC_FREE_LT_CNT(sc), /* nsegments */
86602b553caSRafal Jaworowski SEC_MAX_DMA_BLOCK_SIZE, 0, /* maxsegsz, flags */
86702b553caSRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */
86802b553caSRafal Jaworowski &(dma_mem->dma_tag)); /* dmat */
86902b553caSRafal Jaworowski
87002b553caSRafal Jaworowski if (error) {
87102b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to allocate busdma tag, error"
87202b553caSRafal Jaworowski " %i!\n", error);
87302b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL;
87402b553caSRafal Jaworowski return (error);
87502b553caSRafal Jaworowski }
87602b553caSRafal Jaworowski
87702b553caSRafal Jaworowski error = bus_dmamap_create(dma_mem->dma_tag, 0, &(dma_mem->dma_map));
87802b553caSRafal Jaworowski
87902b553caSRafal Jaworowski if (error) {
88002b553caSRafal Jaworowski device_printf(sc->sc_dev, "failed to create DMA map, error %i!"
88102b553caSRafal Jaworowski "\n", error);
88202b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag);
88302b553caSRafal Jaworowski return (error);
88402b553caSRafal Jaworowski }
88502b553caSRafal Jaworowski
886c0341432SJohn Baldwin error = bus_dmamap_load_crp(dma_mem->dma_tag, dma_mem->dma_map, crp,
887c0341432SJohn Baldwin sec_dma_map_desc_cb, sdmi, BUS_DMA_NOWAIT);
88802b553caSRafal Jaworowski
88902b553caSRafal Jaworowski if (error) {
89002b553caSRafal Jaworowski device_printf(sc->sc_dev, "cannot get address of the DMA"
89102b553caSRafal Jaworowski " memory, error %i!\n", error);
89202b553caSRafal Jaworowski bus_dmamap_destroy(dma_mem->dma_tag, dma_mem->dma_map);
89302b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag);
89402b553caSRafal Jaworowski return (error);
89502b553caSRafal Jaworowski }
89602b553caSRafal Jaworowski
89702b553caSRafal Jaworowski dma_mem->dma_is_map = 1;
898c0341432SJohn Baldwin dma_mem->dma_vaddr = crp;
89902b553caSRafal Jaworowski
90002b553caSRafal Jaworowski return (0);
90102b553caSRafal Jaworowski }
90202b553caSRafal Jaworowski
90302b553caSRafal Jaworowski static void
sec_free_dma_mem(struct sec_dma_mem * dma_mem)90402b553caSRafal Jaworowski sec_free_dma_mem(struct sec_dma_mem *dma_mem)
90502b553caSRafal Jaworowski {
90602b553caSRafal Jaworowski
90702b553caSRafal Jaworowski /* Check for double free */
90802b553caSRafal Jaworowski if (dma_mem->dma_vaddr == NULL)
90902b553caSRafal Jaworowski return;
91002b553caSRafal Jaworowski
91102b553caSRafal Jaworowski bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map);
91202b553caSRafal Jaworowski
91302b553caSRafal Jaworowski if (dma_mem->dma_is_map)
91402b553caSRafal Jaworowski bus_dmamap_destroy(dma_mem->dma_tag, dma_mem->dma_map);
91502b553caSRafal Jaworowski else
91602b553caSRafal Jaworowski bus_dmamem_free(dma_mem->dma_tag, dma_mem->dma_vaddr,
91702b553caSRafal Jaworowski dma_mem->dma_map);
91802b553caSRafal Jaworowski
91902b553caSRafal Jaworowski bus_dma_tag_destroy(dma_mem->dma_tag);
92002b553caSRafal Jaworowski dma_mem->dma_vaddr = NULL;
92102b553caSRafal Jaworowski }
92202b553caSRafal Jaworowski
92302b553caSRafal Jaworowski static int
sec_eu_channel(struct sec_softc * sc,int eu)92402b553caSRafal Jaworowski sec_eu_channel(struct sec_softc *sc, int eu)
92502b553caSRafal Jaworowski {
92602b553caSRafal Jaworowski uint64_t reg;
92702b553caSRafal Jaworowski int channel = 0;
92802b553caSRafal Jaworowski
92902b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, controller);
93002b553caSRafal Jaworowski
93102b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_EUASR);
93202b553caSRafal Jaworowski
93302b553caSRafal Jaworowski switch (eu) {
93402b553caSRafal Jaworowski case SEC_EU_AFEU:
93502b553caSRafal Jaworowski channel = SEC_EUASR_AFEU(reg);
93602b553caSRafal Jaworowski break;
93702b553caSRafal Jaworowski case SEC_EU_DEU:
93802b553caSRafal Jaworowski channel = SEC_EUASR_DEU(reg);
93902b553caSRafal Jaworowski break;
94002b553caSRafal Jaworowski case SEC_EU_MDEU_A:
94102b553caSRafal Jaworowski case SEC_EU_MDEU_B:
94202b553caSRafal Jaworowski channel = SEC_EUASR_MDEU(reg);
94302b553caSRafal Jaworowski break;
94402b553caSRafal Jaworowski case SEC_EU_RNGU:
94502b553caSRafal Jaworowski channel = SEC_EUASR_RNGU(reg);
94602b553caSRafal Jaworowski break;
94702b553caSRafal Jaworowski case SEC_EU_PKEU:
94802b553caSRafal Jaworowski channel = SEC_EUASR_PKEU(reg);
94902b553caSRafal Jaworowski break;
95002b553caSRafal Jaworowski case SEC_EU_AESU:
95102b553caSRafal Jaworowski channel = SEC_EUASR_AESU(reg);
95202b553caSRafal Jaworowski break;
95302b553caSRafal Jaworowski case SEC_EU_KEU:
95402b553caSRafal Jaworowski channel = SEC_EUASR_KEU(reg);
95502b553caSRafal Jaworowski break;
95602b553caSRafal Jaworowski case SEC_EU_CRCU:
95702b553caSRafal Jaworowski channel = SEC_EUASR_CRCU(reg);
95802b553caSRafal Jaworowski break;
95902b553caSRafal Jaworowski }
96002b553caSRafal Jaworowski
96102b553caSRafal Jaworowski return (channel - 1);
96202b553caSRafal Jaworowski }
96302b553caSRafal Jaworowski
96402b553caSRafal Jaworowski static int
sec_enqueue_desc(struct sec_softc * sc,struct sec_desc * desc,int channel)96502b553caSRafal Jaworowski sec_enqueue_desc(struct sec_softc *sc, struct sec_desc *desc, int channel)
96602b553caSRafal Jaworowski {
96702b553caSRafal Jaworowski u_int fflvl = SEC_MAX_FIFO_LEVEL;
96802b553caSRafal Jaworowski uint64_t reg;
96902b553caSRafal Jaworowski int i;
97002b553caSRafal Jaworowski
97102b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, controller);
97202b553caSRafal Jaworowski
97302b553caSRafal Jaworowski /* Find free channel if have not got one */
97402b553caSRafal Jaworowski if (channel < 0) {
97502b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) {
97602b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CSR(channel));
97702b553caSRafal Jaworowski
97802b553caSRafal Jaworowski if ((reg & sc->sc_channel_idle_mask) == 0) {
97902b553caSRafal Jaworowski channel = i;
98002b553caSRafal Jaworowski break;
98102b553caSRafal Jaworowski }
98202b553caSRafal Jaworowski }
98302b553caSRafal Jaworowski }
98402b553caSRafal Jaworowski
98502b553caSRafal Jaworowski /* There is no free channel */
98602b553caSRafal Jaworowski if (channel < 0)
98702b553caSRafal Jaworowski return (-1);
98802b553caSRafal Jaworowski
98902b553caSRafal Jaworowski /* Check FIFO level on selected channel */
99002b553caSRafal Jaworowski reg = SEC_READ(sc, SEC_CHAN_CSR(channel));
99102b553caSRafal Jaworowski
99202b553caSRafal Jaworowski switch(sc->sc_version) {
99302b553caSRafal Jaworowski case 2:
99402b553caSRafal Jaworowski fflvl = (reg >> SEC_CHAN_CSR2_FFLVL_S) & SEC_CHAN_CSR2_FFLVL_M;
99502b553caSRafal Jaworowski break;
99602b553caSRafal Jaworowski case 3:
99702b553caSRafal Jaworowski fflvl = (reg >> SEC_CHAN_CSR3_FFLVL_S) & SEC_CHAN_CSR3_FFLVL_M;
99802b553caSRafal Jaworowski break;
99902b553caSRafal Jaworowski }
100002b553caSRafal Jaworowski
100102b553caSRafal Jaworowski if (fflvl >= SEC_MAX_FIFO_LEVEL)
100202b553caSRafal Jaworowski return (-1);
100302b553caSRafal Jaworowski
100402b553caSRafal Jaworowski /* Enqueue descriptor in channel */
100502b553caSRafal Jaworowski SEC_WRITE(sc, SEC_CHAN_FF(channel), desc->sd_desc_paddr);
100602b553caSRafal Jaworowski
100702b553caSRafal Jaworowski return (channel);
100802b553caSRafal Jaworowski }
100902b553caSRafal Jaworowski
101002b553caSRafal Jaworowski static void
sec_enqueue(struct sec_softc * sc)101102b553caSRafal Jaworowski sec_enqueue(struct sec_softc *sc)
101202b553caSRafal Jaworowski {
101302b553caSRafal Jaworowski struct sec_desc *desc;
101402b553caSRafal Jaworowski int ch0, ch1;
101502b553caSRafal Jaworowski
101602b553caSRafal Jaworowski SEC_LOCK(sc, descriptors);
101702b553caSRafal Jaworowski SEC_LOCK(sc, controller);
101802b553caSRafal Jaworowski
101902b553caSRafal Jaworowski while (SEC_READY_DESC_CNT(sc) > 0) {
102002b553caSRafal Jaworowski desc = SEC_GET_READY_DESC(sc);
102102b553caSRafal Jaworowski
102202b553caSRafal Jaworowski ch0 = sec_eu_channel(sc, desc->sd_desc->shd_eu_sel0);
102302b553caSRafal Jaworowski ch1 = sec_eu_channel(sc, desc->sd_desc->shd_eu_sel1);
102402b553caSRafal Jaworowski
102502b553caSRafal Jaworowski /*
102602b553caSRafal Jaworowski * Both EU are used by the same channel.
102702b553caSRafal Jaworowski * Enqueue descriptor in channel used by busy EUs.
102802b553caSRafal Jaworowski */
102902b553caSRafal Jaworowski if (ch0 >= 0 && ch0 == ch1) {
103002b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, ch0) >= 0) {
103102b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc);
103202b553caSRafal Jaworowski continue;
103302b553caSRafal Jaworowski }
103402b553caSRafal Jaworowski }
103502b553caSRafal Jaworowski
103602b553caSRafal Jaworowski /*
103702b553caSRafal Jaworowski * Only one EU is free.
103802b553caSRafal Jaworowski * Enqueue descriptor in channel used by busy EU.
103902b553caSRafal Jaworowski */
104002b553caSRafal Jaworowski if ((ch0 >= 0 && ch1 < 0) || (ch1 >= 0 && ch0 < 0)) {
104102b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, (ch0 >= 0) ? ch0 : ch1)
104202b553caSRafal Jaworowski >= 0) {
104302b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc);
104402b553caSRafal Jaworowski continue;
104502b553caSRafal Jaworowski }
104602b553caSRafal Jaworowski }
104702b553caSRafal Jaworowski
104802b553caSRafal Jaworowski /*
104902b553caSRafal Jaworowski * Both EU are free.
105002b553caSRafal Jaworowski * Enqueue descriptor in first free channel.
105102b553caSRafal Jaworowski */
105202b553caSRafal Jaworowski if (ch0 < 0 && ch1 < 0) {
105302b553caSRafal Jaworowski if (sec_enqueue_desc(sc, desc, -1) >= 0) {
105402b553caSRafal Jaworowski SEC_DESC_READY2QUEUED(sc);
105502b553caSRafal Jaworowski continue;
105602b553caSRafal Jaworowski }
105702b553caSRafal Jaworowski }
105802b553caSRafal Jaworowski
105902b553caSRafal Jaworowski /* Current descriptor can not be queued at the moment */
106002b553caSRafal Jaworowski SEC_PUT_BACK_READY_DESC(sc);
106102b553caSRafal Jaworowski break;
106202b553caSRafal Jaworowski }
106302b553caSRafal Jaworowski
106402b553caSRafal Jaworowski SEC_UNLOCK(sc, controller);
106502b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
106602b553caSRafal Jaworowski }
106702b553caSRafal Jaworowski
106802b553caSRafal Jaworowski static struct sec_desc *
sec_find_desc(struct sec_softc * sc,bus_addr_t paddr)106902b553caSRafal Jaworowski sec_find_desc(struct sec_softc *sc, bus_addr_t paddr)
107002b553caSRafal Jaworowski {
107102b553caSRafal Jaworowski struct sec_desc *desc = NULL;
107202b553caSRafal Jaworowski int i;
107302b553caSRafal Jaworowski
107402b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors);
107502b553caSRafal Jaworowski
107602b553caSRafal Jaworowski for (i = 0; i < SEC_CHANNELS; i++) {
107702b553caSRafal Jaworowski if (sc->sc_desc[i].sd_desc_paddr == paddr) {
107802b553caSRafal Jaworowski desc = &(sc->sc_desc[i]);
107902b553caSRafal Jaworowski break;
108002b553caSRafal Jaworowski }
108102b553caSRafal Jaworowski }
108202b553caSRafal Jaworowski
108302b553caSRafal Jaworowski return (desc);
108402b553caSRafal Jaworowski }
108502b553caSRafal Jaworowski
108602b553caSRafal Jaworowski static int
sec_make_pointer_direct(struct sec_softc * sc,struct sec_desc * desc,u_int n,bus_addr_t data,bus_size_t dsize)108702b553caSRafal Jaworowski sec_make_pointer_direct(struct sec_softc *sc, struct sec_desc *desc, u_int n,
108802b553caSRafal Jaworowski bus_addr_t data, bus_size_t dsize)
108902b553caSRafal Jaworowski {
109002b553caSRafal Jaworowski struct sec_hw_desc_ptr *ptr;
109102b553caSRafal Jaworowski
109202b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors);
109302b553caSRafal Jaworowski
109402b553caSRafal Jaworowski ptr = &(desc->sd_desc->shd_pointer[n]);
109502b553caSRafal Jaworowski ptr->shdp_length = dsize;
109602b553caSRafal Jaworowski ptr->shdp_extent = 0;
109702b553caSRafal Jaworowski ptr->shdp_j = 0;
109802b553caSRafal Jaworowski ptr->shdp_ptr = data;
109902b553caSRafal Jaworowski
110002b553caSRafal Jaworowski return (0);
110102b553caSRafal Jaworowski }
110202b553caSRafal Jaworowski
110302b553caSRafal Jaworowski static int
sec_make_pointer(struct sec_softc * sc,struct sec_desc * desc,u_int n,struct cryptop * crp,bus_size_t doffset,bus_size_t dsize)110402b553caSRafal Jaworowski sec_make_pointer(struct sec_softc *sc, struct sec_desc *desc,
1105c0341432SJohn Baldwin u_int n, struct cryptop *crp, bus_size_t doffset, bus_size_t dsize)
110602b553caSRafal Jaworowski {
110702b553caSRafal Jaworowski struct sec_desc_map_info sdmi = { sc, dsize, doffset, NULL, NULL, 0 };
110802b553caSRafal Jaworowski struct sec_hw_desc_ptr *ptr;
110902b553caSRafal Jaworowski int error;
111002b553caSRafal Jaworowski
111102b553caSRafal Jaworowski SEC_LOCK_ASSERT(sc, descriptors);
111202b553caSRafal Jaworowski
1113c0341432SJohn Baldwin error = sec_desc_map_dma(sc, &(desc->sd_ptr_dmem[n]), crp, dsize,
1114c0341432SJohn Baldwin &sdmi);
111502b553caSRafal Jaworowski
111602b553caSRafal Jaworowski if (error)
111702b553caSRafal Jaworowski return (error);
111802b553caSRafal Jaworowski
111902b553caSRafal Jaworowski sdmi.sdmi_lt_last->sl_lt->shl_r = 1;
112002b553caSRafal Jaworowski desc->sd_lt_used += sdmi.sdmi_lt_used;
112102b553caSRafal Jaworowski
112202b553caSRafal Jaworowski ptr = &(desc->sd_desc->shd_pointer[n]);
112302b553caSRafal Jaworowski ptr->shdp_length = dsize;
112402b553caSRafal Jaworowski ptr->shdp_extent = 0;
112502b553caSRafal Jaworowski ptr->shdp_j = 1;
112602b553caSRafal Jaworowski ptr->shdp_ptr = sdmi.sdmi_lt_first->sl_lt_paddr;
112702b553caSRafal Jaworowski
112802b553caSRafal Jaworowski return (0);
112902b553caSRafal Jaworowski }
113002b553caSRafal Jaworowski
1131c0341432SJohn Baldwin static bool
sec_cipher_supported(const struct crypto_session_params * csp)1132c0341432SJohn Baldwin sec_cipher_supported(const struct crypto_session_params *csp)
113302b553caSRafal Jaworowski {
113402b553caSRafal Jaworowski
1135c0341432SJohn Baldwin switch (csp->csp_cipher_alg) {
1136c0341432SJohn Baldwin case CRYPTO_AES_CBC:
1137c0341432SJohn Baldwin /* AESU */
1138c0341432SJohn Baldwin if (csp->csp_ivlen != AES_BLOCK_LEN)
1139c0341432SJohn Baldwin return (false);
1140c0341432SJohn Baldwin break;
1141c0341432SJohn Baldwin default:
1142c0341432SJohn Baldwin return (false);
114302b553caSRafal Jaworowski }
114402b553caSRafal Jaworowski
1145c0341432SJohn Baldwin if (csp->csp_cipher_klen == 0 || csp->csp_cipher_klen > SEC_MAX_KEY_LEN)
1146c0341432SJohn Baldwin return (false);
114702b553caSRafal Jaworowski
1148c0341432SJohn Baldwin return (true);
114902b553caSRafal Jaworowski }
115002b553caSRafal Jaworowski
1151c0341432SJohn Baldwin static bool
sec_auth_supported(struct sec_softc * sc,const struct crypto_session_params * csp)1152c0341432SJohn Baldwin sec_auth_supported(struct sec_softc *sc,
1153c0341432SJohn Baldwin const struct crypto_session_params *csp)
115402b553caSRafal Jaworowski {
115502b553caSRafal Jaworowski
1156c0341432SJohn Baldwin switch (csp->csp_auth_alg) {
1157c0341432SJohn Baldwin case CRYPTO_SHA2_384_HMAC:
1158c0341432SJohn Baldwin case CRYPTO_SHA2_512_HMAC:
1159c0341432SJohn Baldwin if (sc->sc_version < 3)
1160c0341432SJohn Baldwin return (false);
1161c0341432SJohn Baldwin /* FALLTHROUGH */
1162c0341432SJohn Baldwin case CRYPTO_SHA1_HMAC:
1163c0341432SJohn Baldwin case CRYPTO_SHA2_256_HMAC:
1164c0341432SJohn Baldwin if (csp->csp_auth_klen > SEC_MAX_KEY_LEN)
1165c0341432SJohn Baldwin return (false);
1166c0341432SJohn Baldwin break;
1167c0341432SJohn Baldwin case CRYPTO_SHA1:
1168c0341432SJohn Baldwin break;
1169c0341432SJohn Baldwin default:
1170c0341432SJohn Baldwin return (false);
117102b553caSRafal Jaworowski }
1172c0341432SJohn Baldwin return (true);
117302b553caSRafal Jaworowski }
117402b553caSRafal Jaworowski
117502b553caSRafal Jaworowski static int
sec_probesession(device_t dev,const struct crypto_session_params * csp)1176c0341432SJohn Baldwin sec_probesession(device_t dev, const struct crypto_session_params *csp)
117702b553caSRafal Jaworowski {
117802b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev);
1179c0341432SJohn Baldwin
1180c0341432SJohn Baldwin if (csp->csp_flags != 0)
1181c0341432SJohn Baldwin return (EINVAL);
1182c0341432SJohn Baldwin switch (csp->csp_mode) {
1183c0341432SJohn Baldwin case CSP_MODE_DIGEST:
1184c0341432SJohn Baldwin if (!sec_auth_supported(sc, csp))
1185c0341432SJohn Baldwin return (EINVAL);
1186c0341432SJohn Baldwin break;
1187c0341432SJohn Baldwin case CSP_MODE_CIPHER:
1188c0341432SJohn Baldwin if (!sec_cipher_supported(csp))
1189c0341432SJohn Baldwin return (EINVAL);
1190c0341432SJohn Baldwin break;
1191c0341432SJohn Baldwin case CSP_MODE_ETA:
1192c0341432SJohn Baldwin if (!sec_auth_supported(sc, csp) || !sec_cipher_supported(csp))
1193c0341432SJohn Baldwin return (EINVAL);
1194c0341432SJohn Baldwin break;
1195c0341432SJohn Baldwin default:
1196c0341432SJohn Baldwin return (EINVAL);
1197c0341432SJohn Baldwin }
1198c0341432SJohn Baldwin return (CRYPTODEV_PROBE_HARDWARE);
1199c0341432SJohn Baldwin }
1200c0341432SJohn Baldwin
1201c0341432SJohn Baldwin static int
sec_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)1202c0341432SJohn Baldwin sec_newsession(device_t dev, crypto_session_t cses,
1203c0341432SJohn Baldwin const struct crypto_session_params *csp)
1204c0341432SJohn Baldwin {
120502b553caSRafal Jaworowski struct sec_eu_methods *eu = sec_eus;
120602b553caSRafal Jaworowski struct sec_session *ses;
120702b553caSRafal Jaworowski
12081b0909d5SConrad Meyer ses = crypto_get_driver_session(cses);
120902b553caSRafal Jaworowski
121002b553caSRafal Jaworowski /* Find EU for this session */
121102b553caSRafal Jaworowski while (eu->sem_make_desc != NULL) {
1212c0341432SJohn Baldwin if (eu->sem_newsession(csp))
121302b553caSRafal Jaworowski break;
121402b553caSRafal Jaworowski eu++;
121502b553caSRafal Jaworowski }
1216c0341432SJohn Baldwin KASSERT(eu->sem_make_desc != NULL, ("failed to find eu for session"));
121702b553caSRafal Jaworowski
121802b553caSRafal Jaworowski /* Save cipher key */
1219c0341432SJohn Baldwin if (csp->csp_cipher_key != NULL)
1220c0341432SJohn Baldwin memcpy(ses->ss_key, csp->csp_cipher_key, csp->csp_cipher_klen);
122102b553caSRafal Jaworowski
122202b553caSRafal Jaworowski /* Save digest key */
1223c0341432SJohn Baldwin if (csp->csp_auth_key != NULL)
1224c0341432SJohn Baldwin memcpy(ses->ss_mkey, csp->csp_auth_key, csp->csp_auth_klen);
1225c0341432SJohn Baldwin
1226c0341432SJohn Baldwin if (csp->csp_auth_alg != 0) {
1227c0341432SJohn Baldwin if (csp->csp_auth_mlen == 0)
1228c0341432SJohn Baldwin ses->ss_mlen = crypto_auth_hash(csp)->hashsize;
1229c0341432SJohn Baldwin else
1230c0341432SJohn Baldwin ses->ss_mlen = csp->csp_auth_mlen;
123102b553caSRafal Jaworowski }
123202b553caSRafal Jaworowski
123302b553caSRafal Jaworowski return (0);
123402b553caSRafal Jaworowski }
123502b553caSRafal Jaworowski
123602b553caSRafal Jaworowski static int
sec_process(device_t dev,struct cryptop * crp,int hint)123702b553caSRafal Jaworowski sec_process(device_t dev, struct cryptop *crp, int hint)
123802b553caSRafal Jaworowski {
123902b553caSRafal Jaworowski struct sec_softc *sc = device_get_softc(dev);
124002b553caSRafal Jaworowski struct sec_desc *desc = NULL;
1241c0341432SJohn Baldwin const struct crypto_session_params *csp;
124202b553caSRafal Jaworowski struct sec_session *ses;
1243c0341432SJohn Baldwin int error = 0;
124402b553caSRafal Jaworowski
12451b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session);
1246c0341432SJohn Baldwin csp = crypto_get_params(crp->crp_session);
124702b553caSRafal Jaworowski
124802b553caSRafal Jaworowski /* Check for input length */
1249b02676a2SJohn Baldwin if (crypto_buffer_len(&crp->crp_buf) > SEC_MAX_DMA_BLOCK_SIZE) {
125002b553caSRafal Jaworowski crp->crp_etype = E2BIG;
125102b553caSRafal Jaworowski crypto_done(crp);
125202b553caSRafal Jaworowski return (0);
125302b553caSRafal Jaworowski }
125402b553caSRafal Jaworowski
125502b553caSRafal Jaworowski SEC_LOCK(sc, descriptors);
125602b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
125702b553caSRafal Jaworowski
125802b553caSRafal Jaworowski /* Block driver if there is no free descriptors or we are going down */
125902b553caSRafal Jaworowski if (SEC_FREE_DESC_CNT(sc) == 0 || sc->sc_shutdown) {
126002b553caSRafal Jaworowski sc->sc_blocked |= CRYPTO_SYMQ;
126102b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
126202b553caSRafal Jaworowski return (ERESTART);
126302b553caSRafal Jaworowski }
126402b553caSRafal Jaworowski
126502b553caSRafal Jaworowski /* Prepare descriptor */
126602b553caSRafal Jaworowski desc = SEC_GET_FREE_DESC(sc);
126702b553caSRafal Jaworowski desc->sd_lt_used = 0;
126802b553caSRafal Jaworowski desc->sd_error = 0;
126902b553caSRafal Jaworowski desc->sd_crp = crp;
127002b553caSRafal Jaworowski
127129fe41ddSJohn Baldwin if (csp->csp_cipher_alg != 0)
127229fe41ddSJohn Baldwin crypto_read_iv(crp, desc->sd_desc->shd_iv);
127302b553caSRafal Jaworowski
1274c0341432SJohn Baldwin if (crp->crp_cipher_key != NULL)
1275c0341432SJohn Baldwin memcpy(ses->ss_key, crp->crp_cipher_key, csp->csp_cipher_klen);
127602b553caSRafal Jaworowski
1277c0341432SJohn Baldwin if (crp->crp_auth_key != NULL)
1278c0341432SJohn Baldwin memcpy(ses->ss_mkey, crp->crp_auth_key, csp->csp_auth_klen);
127902b553caSRafal Jaworowski
1280c0341432SJohn Baldwin memcpy(desc->sd_desc->shd_key, ses->ss_key, csp->csp_cipher_klen);
1281c0341432SJohn Baldwin memcpy(desc->sd_desc->shd_mkey, ses->ss_mkey, csp->csp_auth_klen);
128202b553caSRafal Jaworowski
1283c0341432SJohn Baldwin error = ses->ss_eu->sem_make_desc(sc, csp, desc, crp);
128402b553caSRafal Jaworowski
128502b553caSRafal Jaworowski if (error) {
128602b553caSRafal Jaworowski SEC_DESC_FREE_POINTERS(desc);
128702b553caSRafal Jaworowski SEC_DESC_PUT_BACK_LT(sc, desc);
128802b553caSRafal Jaworowski SEC_PUT_BACK_FREE_DESC(sc);
128902b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
129002b553caSRafal Jaworowski crp->crp_etype = error;
129102b553caSRafal Jaworowski crypto_done(crp);
129202b553caSRafal Jaworowski return (0);
129302b553caSRafal Jaworowski }
129402b553caSRafal Jaworowski
129502b553caSRafal Jaworowski /*
129602b553caSRafal Jaworowski * Skip DONE interrupt if this is not last request in burst, but only
129702b553caSRafal Jaworowski * if we are running on SEC 3.X. On SEC 2.X we have to enable DONE
129802b553caSRafal Jaworowski * signaling on each descriptor.
129902b553caSRafal Jaworowski */
130002b553caSRafal Jaworowski if ((hint & CRYPTO_HINT_MORE) && sc->sc_version == 3)
130102b553caSRafal Jaworowski desc->sd_desc->shd_dn = 0;
130202b553caSRafal Jaworowski else
130302b553caSRafal Jaworowski desc->sd_desc->shd_dn = 1;
130402b553caSRafal Jaworowski
130502b553caSRafal Jaworowski SEC_DESC_SYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
130602b553caSRafal Jaworowski SEC_DESC_SYNC_POINTERS(desc, BUS_DMASYNC_POSTREAD |
130702b553caSRafal Jaworowski BUS_DMASYNC_POSTWRITE);
130802b553caSRafal Jaworowski SEC_DESC_FREE2READY(sc);
130902b553caSRafal Jaworowski SEC_UNLOCK(sc, descriptors);
131002b553caSRafal Jaworowski
131102b553caSRafal Jaworowski /* Enqueue ready descriptors in hardware */
131202b553caSRafal Jaworowski sec_enqueue(sc);
131302b553caSRafal Jaworowski
131402b553caSRafal Jaworowski return (0);
131502b553caSRafal Jaworowski }
131602b553caSRafal Jaworowski
131702b553caSRafal Jaworowski static int
sec_build_common_ns_desc(struct sec_softc * sc,struct sec_desc * desc,const struct crypto_session_params * csp,struct cryptop * crp)131802b553caSRafal Jaworowski sec_build_common_ns_desc(struct sec_softc *sc, struct sec_desc *desc,
1319c0341432SJohn Baldwin const struct crypto_session_params *csp, struct cryptop *crp)
132002b553caSRafal Jaworowski {
132102b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc;
132202b553caSRafal Jaworowski int error;
132302b553caSRafal Jaworowski
132402b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_COMMON_NONSNOOP;
132502b553caSRafal Jaworowski hd->shd_eu_sel1 = SEC_EU_NONE;
132602b553caSRafal Jaworowski hd->shd_mode1 = 0;
132702b553caSRafal Jaworowski
132802b553caSRafal Jaworowski /* Pointer 0: NULL */
132902b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, 0, 0);
133002b553caSRafal Jaworowski if (error)
133102b553caSRafal Jaworowski return (error);
133202b553caSRafal Jaworowski
133302b553caSRafal Jaworowski /* Pointer 1: IV IN */
133402b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 1, desc->sd_desc_paddr +
1335c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen);
133602b553caSRafal Jaworowski if (error)
133702b553caSRafal Jaworowski return (error);
133802b553caSRafal Jaworowski
133902b553caSRafal Jaworowski /* Pointer 2: Cipher Key */
134002b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr +
1341c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen);
134202b553caSRafal Jaworowski if (error)
134302b553caSRafal Jaworowski return (error);
134402b553caSRafal Jaworowski
134502b553caSRafal Jaworowski /* Pointer 3: Data IN */
1346c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start,
1347c0341432SJohn Baldwin crp->crp_payload_length);
134802b553caSRafal Jaworowski if (error)
134902b553caSRafal Jaworowski return (error);
135002b553caSRafal Jaworowski
135102b553caSRafal Jaworowski /* Pointer 4: Data OUT */
1352c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start,
1353c0341432SJohn Baldwin crp->crp_payload_length);
135402b553caSRafal Jaworowski if (error)
135502b553caSRafal Jaworowski return (error);
135602b553caSRafal Jaworowski
135702b553caSRafal Jaworowski /* Pointer 5: IV OUT (Not used: NULL) */
135802b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 5, 0, 0);
135902b553caSRafal Jaworowski if (error)
136002b553caSRafal Jaworowski return (error);
136102b553caSRafal Jaworowski
136202b553caSRafal Jaworowski /* Pointer 6: NULL */
136302b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 6, 0, 0);
136402b553caSRafal Jaworowski
136502b553caSRafal Jaworowski return (error);
136602b553caSRafal Jaworowski }
136702b553caSRafal Jaworowski
136802b553caSRafal Jaworowski static int
sec_build_common_s_desc(struct sec_softc * sc,struct sec_desc * desc,const struct crypto_session_params * csp,struct cryptop * crp)136902b553caSRafal Jaworowski sec_build_common_s_desc(struct sec_softc *sc, struct sec_desc *desc,
1370c0341432SJohn Baldwin const struct crypto_session_params *csp, struct cryptop *crp)
137102b553caSRafal Jaworowski {
137202b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc;
137302b553caSRafal Jaworowski u_int eu, mode, hashlen;
137402b553caSRafal Jaworowski int error;
137502b553caSRafal Jaworowski
1376c0341432SJohn Baldwin error = sec_mdeu_config(csp, &eu, &mode, &hashlen);
137702b553caSRafal Jaworowski if (error)
137802b553caSRafal Jaworowski return (error);
137902b553caSRafal Jaworowski
138002b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_HMAC_SNOOP;
138102b553caSRafal Jaworowski hd->shd_eu_sel1 = eu;
138202b553caSRafal Jaworowski hd->shd_mode1 = mode;
138302b553caSRafal Jaworowski
138402b553caSRafal Jaworowski /* Pointer 0: HMAC Key */
138502b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, desc->sd_desc_paddr +
1386c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_mkey), csp->csp_auth_klen);
138702b553caSRafal Jaworowski if (error)
138802b553caSRafal Jaworowski return (error);
138902b553caSRafal Jaworowski
139002b553caSRafal Jaworowski /* Pointer 1: HMAC-Only Data IN */
1391c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 1, crp, crp->crp_aad_start,
1392c0341432SJohn Baldwin crp->crp_aad_length);
139302b553caSRafal Jaworowski if (error)
139402b553caSRafal Jaworowski return (error);
139502b553caSRafal Jaworowski
139602b553caSRafal Jaworowski /* Pointer 2: Cipher Key */
139702b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, desc->sd_desc_paddr +
1398c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_key), csp->csp_cipher_klen);
139902b553caSRafal Jaworowski if (error)
140002b553caSRafal Jaworowski return (error);
140102b553caSRafal Jaworowski
140202b553caSRafal Jaworowski /* Pointer 3: IV IN */
140302b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 3, desc->sd_desc_paddr +
1404c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_iv), csp->csp_ivlen);
140502b553caSRafal Jaworowski if (error)
140602b553caSRafal Jaworowski return (error);
140702b553caSRafal Jaworowski
140802b553caSRafal Jaworowski /* Pointer 4: Data IN */
1409c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 4, crp, crp->crp_payload_start,
1410c0341432SJohn Baldwin crp->crp_payload_length);
141102b553caSRafal Jaworowski if (error)
141202b553caSRafal Jaworowski return (error);
141302b553caSRafal Jaworowski
141402b553caSRafal Jaworowski /* Pointer 5: Data OUT */
1415c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 5, crp, crp->crp_payload_start,
1416c0341432SJohn Baldwin crp->crp_payload_length);
141702b553caSRafal Jaworowski if (error)
141802b553caSRafal Jaworowski return (error);
141902b553caSRafal Jaworowski
142002b553caSRafal Jaworowski /* Pointer 6: HMAC OUT */
1421c0341432SJohn Baldwin error = sec_make_pointer_direct(sc, desc, 6, desc->sd_desc_paddr +
1422c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_digest), hashlen);
142302b553caSRafal Jaworowski
142402b553caSRafal Jaworowski return (error);
142502b553caSRafal Jaworowski }
142602b553caSRafal Jaworowski
142702b553caSRafal Jaworowski /* AESU */
142802b553caSRafal Jaworowski
1429c0341432SJohn Baldwin static bool
sec_aesu_newsession(const struct crypto_session_params * csp)1430c0341432SJohn Baldwin sec_aesu_newsession(const struct crypto_session_params *csp)
143102b553caSRafal Jaworowski {
143202b553caSRafal Jaworowski
1433c0341432SJohn Baldwin return (csp->csp_cipher_alg == CRYPTO_AES_CBC);
143402b553caSRafal Jaworowski }
143502b553caSRafal Jaworowski
143602b553caSRafal Jaworowski static int
sec_aesu_make_desc(struct sec_softc * sc,const struct crypto_session_params * csp,struct sec_desc * desc,struct cryptop * crp)1437c0341432SJohn Baldwin sec_aesu_make_desc(struct sec_softc *sc,
1438c0341432SJohn Baldwin const struct crypto_session_params *csp, struct sec_desc *desc,
1439c0341432SJohn Baldwin struct cryptop *crp)
144002b553caSRafal Jaworowski {
144102b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc;
144202b553caSRafal Jaworowski int error;
144302b553caSRafal Jaworowski
144402b553caSRafal Jaworowski hd->shd_eu_sel0 = SEC_EU_AESU;
144502b553caSRafal Jaworowski hd->shd_mode0 = SEC_AESU_MODE_CBC;
144602b553caSRafal Jaworowski
1447c0341432SJohn Baldwin if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
144802b553caSRafal Jaworowski hd->shd_mode0 |= SEC_AESU_MODE_ED;
144902b553caSRafal Jaworowski hd->shd_dir = 0;
145002b553caSRafal Jaworowski } else
145102b553caSRafal Jaworowski hd->shd_dir = 1;
145202b553caSRafal Jaworowski
1453c0341432SJohn Baldwin if (csp->csp_mode == CSP_MODE_ETA)
1454c0341432SJohn Baldwin error = sec_build_common_s_desc(sc, desc, csp, crp);
145502b553caSRafal Jaworowski else
1456c0341432SJohn Baldwin error = sec_build_common_ns_desc(sc, desc, csp, crp);
145702b553caSRafal Jaworowski
145802b553caSRafal Jaworowski return (error);
145902b553caSRafal Jaworowski }
146002b553caSRafal Jaworowski
146102b553caSRafal Jaworowski /* MDEU */
146202b553caSRafal Jaworowski
1463c0341432SJohn Baldwin static bool
sec_mdeu_can_handle(u_int alg)146402b553caSRafal Jaworowski sec_mdeu_can_handle(u_int alg)
146502b553caSRafal Jaworowski {
146602b553caSRafal Jaworowski switch (alg) {
146702b553caSRafal Jaworowski case CRYPTO_SHA1:
146802b553caSRafal Jaworowski case CRYPTO_SHA1_HMAC:
146902b553caSRafal Jaworowski case CRYPTO_SHA2_256_HMAC:
147002b553caSRafal Jaworowski case CRYPTO_SHA2_384_HMAC:
147102b553caSRafal Jaworowski case CRYPTO_SHA2_512_HMAC:
1472c0341432SJohn Baldwin return (true);
147302b553caSRafal Jaworowski default:
1474c0341432SJohn Baldwin return (false);
147502b553caSRafal Jaworowski }
147602b553caSRafal Jaworowski }
147702b553caSRafal Jaworowski
147802b553caSRafal Jaworowski static int
sec_mdeu_config(const struct crypto_session_params * csp,u_int * eu,u_int * mode,u_int * hashlen)1479c0341432SJohn Baldwin sec_mdeu_config(const struct crypto_session_params *csp, u_int *eu, u_int *mode,
1480c0341432SJohn Baldwin u_int *hashlen)
148102b553caSRafal Jaworowski {
148202b553caSRafal Jaworowski
148302b553caSRafal Jaworowski *mode = SEC_MDEU_MODE_PD | SEC_MDEU_MODE_INIT;
148402b553caSRafal Jaworowski *eu = SEC_EU_NONE;
148502b553caSRafal Jaworowski
1486c0341432SJohn Baldwin switch (csp->csp_auth_alg) {
148702b553caSRafal Jaworowski case CRYPTO_SHA1_HMAC:
148802b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC;
148902b553caSRafal Jaworowski /* FALLTHROUGH */
149002b553caSRafal Jaworowski case CRYPTO_SHA1:
149102b553caSRafal Jaworowski *eu = SEC_EU_MDEU_A;
149202b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_SHA1;
149302b553caSRafal Jaworowski *hashlen = SHA1_HASH_LEN;
149402b553caSRafal Jaworowski break;
149502b553caSRafal Jaworowski case CRYPTO_SHA2_256_HMAC:
149602b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA256;
149702b553caSRafal Jaworowski *eu = SEC_EU_MDEU_A;
149802b553caSRafal Jaworowski break;
149902b553caSRafal Jaworowski case CRYPTO_SHA2_384_HMAC:
150002b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA384;
150102b553caSRafal Jaworowski *eu = SEC_EU_MDEU_B;
150202b553caSRafal Jaworowski break;
150302b553caSRafal Jaworowski case CRYPTO_SHA2_512_HMAC:
150402b553caSRafal Jaworowski *mode |= SEC_MDEU_MODE_HMAC | SEC_MDEU_MODE_SHA512;
150502b553caSRafal Jaworowski *eu = SEC_EU_MDEU_B;
150602b553caSRafal Jaworowski break;
150702b553caSRafal Jaworowski default:
150802b553caSRafal Jaworowski return (EINVAL);
150902b553caSRafal Jaworowski }
151002b553caSRafal Jaworowski
151102b553caSRafal Jaworowski if (*mode & SEC_MDEU_MODE_HMAC)
151202b553caSRafal Jaworowski *hashlen = SEC_HMAC_HASH_LEN;
151302b553caSRafal Jaworowski
151402b553caSRafal Jaworowski return (0);
151502b553caSRafal Jaworowski }
151602b553caSRafal Jaworowski
1517c0341432SJohn Baldwin static bool
sec_mdeu_newsession(const struct crypto_session_params * csp)1518c0341432SJohn Baldwin sec_mdeu_newsession(const struct crypto_session_params *csp)
151902b553caSRafal Jaworowski {
152002b553caSRafal Jaworowski
1521c0341432SJohn Baldwin return (sec_mdeu_can_handle(csp->csp_auth_alg));
152202b553caSRafal Jaworowski }
152302b553caSRafal Jaworowski
152402b553caSRafal Jaworowski static int
sec_mdeu_make_desc(struct sec_softc * sc,const struct crypto_session_params * csp,struct sec_desc * desc,struct cryptop * crp)1525c0341432SJohn Baldwin sec_mdeu_make_desc(struct sec_softc *sc,
1526c0341432SJohn Baldwin const struct crypto_session_params *csp,
1527c0341432SJohn Baldwin struct sec_desc *desc, struct cryptop *crp)
152802b553caSRafal Jaworowski {
152902b553caSRafal Jaworowski struct sec_hw_desc *hd = desc->sd_desc;
153002b553caSRafal Jaworowski u_int eu, mode, hashlen;
153102b553caSRafal Jaworowski int error;
153202b553caSRafal Jaworowski
1533c0341432SJohn Baldwin error = sec_mdeu_config(csp, &eu, &mode, &hashlen);
153402b553caSRafal Jaworowski if (error)
153502b553caSRafal Jaworowski return (error);
153602b553caSRafal Jaworowski
153702b553caSRafal Jaworowski hd->shd_desc_type = SEC_DT_COMMON_NONSNOOP;
153802b553caSRafal Jaworowski hd->shd_eu_sel0 = eu;
153902b553caSRafal Jaworowski hd->shd_mode0 = mode;
154002b553caSRafal Jaworowski hd->shd_eu_sel1 = SEC_EU_NONE;
154102b553caSRafal Jaworowski hd->shd_mode1 = 0;
154202b553caSRafal Jaworowski
154302b553caSRafal Jaworowski /* Pointer 0: NULL */
154402b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 0, 0, 0);
154502b553caSRafal Jaworowski if (error)
154602b553caSRafal Jaworowski return (error);
154702b553caSRafal Jaworowski
154802b553caSRafal Jaworowski /* Pointer 1: Context In (Not used: NULL) */
154902b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 1, 0, 0);
155002b553caSRafal Jaworowski if (error)
155102b553caSRafal Jaworowski return (error);
155202b553caSRafal Jaworowski
155302b553caSRafal Jaworowski /* Pointer 2: HMAC Key (or NULL, depending on digest type) */
155402b553caSRafal Jaworowski if (hd->shd_mode0 & SEC_MDEU_MODE_HMAC)
155502b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2,
155602b553caSRafal Jaworowski desc->sd_desc_paddr + offsetof(struct sec_hw_desc,
1557c0341432SJohn Baldwin shd_mkey), csp->csp_auth_klen);
155802b553caSRafal Jaworowski else
155902b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 2, 0, 0);
156002b553caSRafal Jaworowski
156102b553caSRafal Jaworowski if (error)
156202b553caSRafal Jaworowski return (error);
156302b553caSRafal Jaworowski
156402b553caSRafal Jaworowski /* Pointer 3: Input Data */
1565c0341432SJohn Baldwin error = sec_make_pointer(sc, desc, 3, crp, crp->crp_payload_start,
1566c0341432SJohn Baldwin crp->crp_payload_length);
156702b553caSRafal Jaworowski if (error)
156802b553caSRafal Jaworowski return (error);
156902b553caSRafal Jaworowski
157002b553caSRafal Jaworowski /* Pointer 4: NULL */
157102b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 4, 0, 0);
157202b553caSRafal Jaworowski if (error)
157302b553caSRafal Jaworowski return (error);
157402b553caSRafal Jaworowski
157502b553caSRafal Jaworowski /* Pointer 5: Hash out */
1576c0341432SJohn Baldwin error = sec_make_pointer_direct(sc, desc, 5, desc->sd_desc_paddr +
1577c0341432SJohn Baldwin offsetof(struct sec_hw_desc, shd_digest), hashlen);
157802b553caSRafal Jaworowski if (error)
157902b553caSRafal Jaworowski return (error);
158002b553caSRafal Jaworowski
158102b553caSRafal Jaworowski /* Pointer 6: NULL */
158202b553caSRafal Jaworowski error = sec_make_pointer_direct(sc, desc, 6, 0, 0);
158302b553caSRafal Jaworowski
158402b553caSRafal Jaworowski return (0);
158502b553caSRafal Jaworowski }
1586