]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cesa/cesa.c
Import lib9p 7ddb1164407da19b9b1afb83df83ae65a71a9a66.
[FreeBSD/FreeBSD.git] / sys / dev / cesa / cesa.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (C) 2009-2011 Semihalf.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * CESA SRAM Memory Map:
31  *
32  * +------------------------+ <= sc->sc_sram_base_va + CESA_SRAM_SIZE
33  * |                        |
34  * |          DATA          |
35  * |                        |
36  * +------------------------+ <= sc->sc_sram_base_va + CESA_DATA(0)
37  * |  struct cesa_sa_data   |
38  * +------------------------+
39  * |  struct cesa_sa_hdesc  |
40  * +------------------------+ <= sc->sc_sram_base_va
41  */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/bus.h>
49 #include <sys/endian.h>
50 #include <sys/kernel.h>
51 #include <sys/lock.h>
52 #include <sys/mbuf.h>
53 #include <sys/module.h>
54 #include <sys/mutex.h>
55 #include <sys/rman.h>
56
57 #include <machine/bus.h>
58 #include <machine/intr.h>
59 #include <machine/resource.h>
60 #include <machine/fdt.h>
61
62 #include <dev/fdt/simplebus.h>
63 #include <dev/fdt/fdt_common.h>
64 #include <dev/ofw/ofw_bus.h>
65 #include <dev/ofw/ofw_bus_subr.h>
66
67 #include <crypto/sha1.h>
68 #include <crypto/sha2/sha256.h>
69 #include <crypto/rijndael/rijndael.h>
70 #include <opencrypto/cryptodev.h>
71 #include <opencrypto/xform.h>
72 #include "cryptodev_if.h"
73
74 #include <arm/mv/mvreg.h>
75 #include <arm/mv/mvvar.h>
76 #include "cesa.h"
77
78 static int      cesa_probe(device_t);
79 static int      cesa_attach(device_t);
80 static int      cesa_attach_late(device_t);
81 static int      cesa_detach(device_t);
82 static void     cesa_intr(void *);
83 static int      cesa_probesession(device_t,
84     const struct crypto_session_params *);
85 static int      cesa_newsession(device_t, crypto_session_t,
86     const struct crypto_session_params *);
87 static int      cesa_process(device_t, struct cryptop *, int);
88
89 static struct resource_spec cesa_res_spec[] = {
90         { SYS_RES_MEMORY, 0, RF_ACTIVE },
91         { SYS_RES_MEMORY, 1, RF_ACTIVE },
92         { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
93         { -1, 0 }
94 };
95
96 static device_method_t cesa_methods[] = {
97         /* Device interface */
98         DEVMETHOD(device_probe,         cesa_probe),
99         DEVMETHOD(device_attach,        cesa_attach),
100         DEVMETHOD(device_detach,        cesa_detach),
101
102         /* Crypto device methods */
103         DEVMETHOD(cryptodev_probesession, cesa_probesession),
104         DEVMETHOD(cryptodev_newsession, cesa_newsession),
105         DEVMETHOD(cryptodev_process,    cesa_process),
106
107         DEVMETHOD_END
108 };
109
110 static driver_t cesa_driver = {
111         "cesa",
112         cesa_methods,
113         sizeof (struct cesa_softc)
114 };
115 static devclass_t cesa_devclass;
116
117 DRIVER_MODULE(cesa, simplebus, cesa_driver, cesa_devclass, 0, 0);
118 MODULE_DEPEND(cesa, crypto, 1, 1, 1);
119
120 static void
121 cesa_dump_cshd(struct cesa_softc *sc, struct cesa_sa_hdesc *cshd)
122 {
123 #ifdef DEBUG
124         device_t dev;
125
126         dev = sc->sc_dev;
127         device_printf(dev, "CESA SA Hardware Descriptor:\n");
128         device_printf(dev, "\t\tconfig: 0x%08X\n", cshd->cshd_config);
129         device_printf(dev, "\t\te_src:  0x%08X\n", cshd->cshd_enc_src);
130         device_printf(dev, "\t\te_dst:  0x%08X\n", cshd->cshd_enc_dst);
131         device_printf(dev, "\t\te_dlen: 0x%08X\n", cshd->cshd_enc_dlen);
132         device_printf(dev, "\t\te_key:  0x%08X\n", cshd->cshd_enc_key);
133         device_printf(dev, "\t\te_iv_1: 0x%08X\n", cshd->cshd_enc_iv);
134         device_printf(dev, "\t\te_iv_2: 0x%08X\n", cshd->cshd_enc_iv_buf);
135         device_printf(dev, "\t\tm_src:  0x%08X\n", cshd->cshd_mac_src);
136         device_printf(dev, "\t\tm_dst:  0x%08X\n", cshd->cshd_mac_dst);
137         device_printf(dev, "\t\tm_dlen: 0x%08X\n", cshd->cshd_mac_dlen);
138         device_printf(dev, "\t\tm_tlen: 0x%08X\n", cshd->cshd_mac_total_dlen);
139         device_printf(dev, "\t\tm_iv_i: 0x%08X\n", cshd->cshd_mac_iv_in);
140         device_printf(dev, "\t\tm_iv_o: 0x%08X\n", cshd->cshd_mac_iv_out);
141 #endif
142 }
143
144 static void
145 cesa_alloc_dma_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
146 {
147         struct cesa_dma_mem *cdm;
148
149         if (error)
150                 return;
151
152         KASSERT(nseg == 1, ("Got wrong number of DMA segments, should be 1."));
153         cdm = arg;
154         cdm->cdm_paddr = segs->ds_addr;
155 }
156
157 static int
158 cesa_alloc_dma_mem(struct cesa_softc *sc, struct cesa_dma_mem *cdm,
159     bus_size_t size)
160 {
161         int error;
162
163         KASSERT(cdm->cdm_vaddr == NULL,
164             ("%s(): DMA memory descriptor in use.", __func__));
165
166         error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
167             PAGE_SIZE, 0,                       /* alignment, boundary */
168             BUS_SPACE_MAXADDR_32BIT,            /* lowaddr */
169             BUS_SPACE_MAXADDR,                  /* highaddr */
170             NULL, NULL,                         /* filtfunc, filtfuncarg */
171             size, 1,                            /* maxsize, nsegments */
172             size, 0,                            /* maxsegsz, flags */
173             NULL, NULL,                         /* lockfunc, lockfuncarg */
174             &cdm->cdm_tag);                     /* dmat */
175         if (error) {
176                 device_printf(sc->sc_dev, "failed to allocate busdma tag, error"
177                     " %i!\n", error);
178
179                 goto err1;
180         }
181
182         error = bus_dmamem_alloc(cdm->cdm_tag, &cdm->cdm_vaddr,
183             BUS_DMA_NOWAIT | BUS_DMA_ZERO, &cdm->cdm_map);
184         if (error) {
185                 device_printf(sc->sc_dev, "failed to allocate DMA safe"
186                     " memory, error %i!\n", error);
187
188                 goto err2;
189         }
190
191         error = bus_dmamap_load(cdm->cdm_tag, cdm->cdm_map, cdm->cdm_vaddr,
192             size, cesa_alloc_dma_mem_cb, cdm, BUS_DMA_NOWAIT);
193         if (error) {
194                 device_printf(sc->sc_dev, "cannot get address of the DMA"
195                     " memory, error %i\n", error);
196
197                 goto err3;
198         }
199
200         return (0);
201 err3:
202         bus_dmamem_free(cdm->cdm_tag, cdm->cdm_vaddr, cdm->cdm_map);
203 err2:
204         bus_dma_tag_destroy(cdm->cdm_tag);
205 err1:
206         cdm->cdm_vaddr = NULL;
207         return (error);
208 }
209
210 static void
211 cesa_free_dma_mem(struct cesa_dma_mem *cdm)
212 {
213
214         bus_dmamap_unload(cdm->cdm_tag, cdm->cdm_map);
215         bus_dmamem_free(cdm->cdm_tag, cdm->cdm_vaddr, cdm->cdm_map);
216         bus_dma_tag_destroy(cdm->cdm_tag);
217         cdm->cdm_vaddr = NULL;
218 }
219
220 static void
221 cesa_sync_dma_mem(struct cesa_dma_mem *cdm, bus_dmasync_op_t op)
222 {
223
224         /* Sync only if dma memory is valid */
225         if (cdm->cdm_vaddr != NULL)
226                 bus_dmamap_sync(cdm->cdm_tag, cdm->cdm_map, op);
227 }
228
229 static void
230 cesa_sync_desc(struct cesa_softc *sc, bus_dmasync_op_t op)
231 {
232
233         cesa_sync_dma_mem(&sc->sc_tdesc_cdm, op);
234         cesa_sync_dma_mem(&sc->sc_sdesc_cdm, op);
235         cesa_sync_dma_mem(&sc->sc_requests_cdm, op);
236 }
237
238 static struct cesa_request *
239 cesa_alloc_request(struct cesa_softc *sc)
240 {
241         struct cesa_request *cr;
242
243         CESA_GENERIC_ALLOC_LOCKED(sc, cr, requests);
244         if (!cr)
245                 return (NULL);
246
247         STAILQ_INIT(&cr->cr_tdesc);
248         STAILQ_INIT(&cr->cr_sdesc);
249
250         return (cr);
251 }
252
253 static void
254 cesa_free_request(struct cesa_softc *sc, struct cesa_request *cr)
255 {
256
257         /* Free TDMA descriptors assigned to this request */
258         CESA_LOCK(sc, tdesc);
259         STAILQ_CONCAT(&sc->sc_free_tdesc, &cr->cr_tdesc);
260         CESA_UNLOCK(sc, tdesc);
261
262         /* Free SA descriptors assigned to this request */
263         CESA_LOCK(sc, sdesc);
264         STAILQ_CONCAT(&sc->sc_free_sdesc, &cr->cr_sdesc);
265         CESA_UNLOCK(sc, sdesc);
266
267         /* Unload DMA memory associated with request */
268         if (cr->cr_dmap_loaded) {
269                 bus_dmamap_unload(sc->sc_data_dtag, cr->cr_dmap);
270                 cr->cr_dmap_loaded = 0;
271         }
272
273         CESA_GENERIC_FREE_LOCKED(sc, cr, requests);
274 }
275
276 static void
277 cesa_enqueue_request(struct cesa_softc *sc, struct cesa_request *cr)
278 {
279
280         CESA_LOCK(sc, requests);
281         STAILQ_INSERT_TAIL(&sc->sc_ready_requests, cr, cr_stq);
282         CESA_UNLOCK(sc, requests);
283 }
284
285 static struct cesa_tdma_desc *
286 cesa_alloc_tdesc(struct cesa_softc *sc)
287 {
288         struct cesa_tdma_desc *ctd;
289
290         CESA_GENERIC_ALLOC_LOCKED(sc, ctd, tdesc);
291
292         if (!ctd)
293                 device_printf(sc->sc_dev, "TDMA descriptors pool exhaused. "
294                     "Consider increasing CESA_TDMA_DESCRIPTORS.\n");
295
296         return (ctd);
297 }
298
299 static struct cesa_sa_desc *
300 cesa_alloc_sdesc(struct cesa_softc *sc, struct cesa_request *cr)
301 {
302         struct cesa_sa_desc *csd;
303
304         CESA_GENERIC_ALLOC_LOCKED(sc, csd, sdesc);
305         if (!csd) {
306                 device_printf(sc->sc_dev, "SA descriptors pool exhaused. "
307                     "Consider increasing CESA_SA_DESCRIPTORS.\n");
308                 return (NULL);
309         }
310
311         STAILQ_INSERT_TAIL(&cr->cr_sdesc, csd, csd_stq);
312
313         /* Fill-in SA descriptor with default values */
314         csd->csd_cshd->cshd_enc_key = CESA_SA_DATA(csd_key);
315         csd->csd_cshd->cshd_enc_iv = CESA_SA_DATA(csd_iv);
316         csd->csd_cshd->cshd_enc_iv_buf = CESA_SA_DATA(csd_iv);
317         csd->csd_cshd->cshd_enc_src = 0;
318         csd->csd_cshd->cshd_enc_dst = 0;
319         csd->csd_cshd->cshd_enc_dlen = 0;
320         csd->csd_cshd->cshd_mac_dst = CESA_SA_DATA(csd_hash);
321         csd->csd_cshd->cshd_mac_iv_in = CESA_SA_DATA(csd_hiv_in);
322         csd->csd_cshd->cshd_mac_iv_out = CESA_SA_DATA(csd_hiv_out);
323         csd->csd_cshd->cshd_mac_src = 0;
324         csd->csd_cshd->cshd_mac_dlen = 0;
325
326         return (csd);
327 }
328
329 static struct cesa_tdma_desc *
330 cesa_tdma_copy(struct cesa_softc *sc, bus_addr_t dst, bus_addr_t src,
331     bus_size_t size)
332 {
333         struct cesa_tdma_desc *ctd;
334
335         ctd = cesa_alloc_tdesc(sc);
336         if (!ctd)
337                 return (NULL);
338
339         ctd->ctd_cthd->cthd_dst = dst;
340         ctd->ctd_cthd->cthd_src = src;
341         ctd->ctd_cthd->cthd_byte_count = size;
342
343         /* Handle special control packet */
344         if (size != 0)
345                 ctd->ctd_cthd->cthd_flags = CESA_CTHD_OWNED;
346         else
347                 ctd->ctd_cthd->cthd_flags = 0;
348
349         return (ctd);
350 }
351
352 static struct cesa_tdma_desc *
353 cesa_tdma_copyin_sa_data(struct cesa_softc *sc, struct cesa_request *cr)
354 {
355
356         return (cesa_tdma_copy(sc, sc->sc_sram_base_pa +
357             sizeof(struct cesa_sa_hdesc), cr->cr_csd_paddr,
358             sizeof(struct cesa_sa_data)));
359 }
360
361 static struct cesa_tdma_desc *
362 cesa_tdma_copyout_sa_data(struct cesa_softc *sc, struct cesa_request *cr)
363 {
364
365         return (cesa_tdma_copy(sc, cr->cr_csd_paddr, sc->sc_sram_base_pa +
366             sizeof(struct cesa_sa_hdesc), sizeof(struct cesa_sa_data)));
367 }
368
369 static struct cesa_tdma_desc *
370 cesa_tdma_copy_sdesc(struct cesa_softc *sc, struct cesa_sa_desc *csd)
371 {
372
373         return (cesa_tdma_copy(sc, sc->sc_sram_base_pa, csd->csd_cshd_paddr,
374             sizeof(struct cesa_sa_hdesc)));
375 }
376
377 static void
378 cesa_append_tdesc(struct cesa_request *cr, struct cesa_tdma_desc *ctd)
379 {
380         struct cesa_tdma_desc *ctd_prev;
381
382         if (!STAILQ_EMPTY(&cr->cr_tdesc)) {
383                 ctd_prev = STAILQ_LAST(&cr->cr_tdesc, cesa_tdma_desc, ctd_stq);
384                 ctd_prev->ctd_cthd->cthd_next = ctd->ctd_cthd_paddr;
385         }
386
387         ctd->ctd_cthd->cthd_next = 0;
388         STAILQ_INSERT_TAIL(&cr->cr_tdesc, ctd, ctd_stq);
389 }
390
391 static int
392 cesa_append_packet(struct cesa_softc *sc, struct cesa_request *cr,
393     struct cesa_packet *cp, struct cesa_sa_desc *csd)
394 {
395         struct cesa_tdma_desc *ctd, *tmp;
396
397         /* Copy SA descriptor for this packet */
398         ctd = cesa_tdma_copy_sdesc(sc, csd);
399         if (!ctd)
400                 return (ENOMEM);
401
402         cesa_append_tdesc(cr, ctd);
403
404         /* Copy data to be processed */
405         STAILQ_FOREACH_SAFE(ctd, &cp->cp_copyin, ctd_stq, tmp)
406                 cesa_append_tdesc(cr, ctd);
407         STAILQ_INIT(&cp->cp_copyin);
408
409         /* Insert control descriptor */
410         ctd = cesa_tdma_copy(sc, 0, 0, 0);
411         if (!ctd)
412                 return (ENOMEM);
413
414         cesa_append_tdesc(cr, ctd);
415
416         /* Copy back results */
417         STAILQ_FOREACH_SAFE(ctd, &cp->cp_copyout, ctd_stq, tmp)
418                 cesa_append_tdesc(cr, ctd);
419         STAILQ_INIT(&cp->cp_copyout);
420
421         return (0);
422 }
423
424 static void
425 cesa_set_mkey(struct cesa_session *cs, int alg, const uint8_t *mkey, int mklen)
426 {
427         union authctx auth_ctx;
428         uint32_t *hout;
429         uint32_t *hin;
430         int i;
431
432         hin = (uint32_t *)cs->cs_hiv_in;
433         hout = (uint32_t *)cs->cs_hiv_out;
434
435         switch (alg) {
436         case CRYPTO_SHA1_HMAC:
437                 hmac_init_ipad(&auth_hash_hmac_sha1, mkey, mklen, &auth_ctx);
438                 memcpy(hin, auth_ctx.sha1ctx.h.b32,
439                     sizeof(auth_ctx.sha1ctx.h.b32));
440                 hmac_init_opad(&auth_hash_hmac_sha1, mkey, mklen, &auth_ctx);
441                 memcpy(hout, auth_ctx.sha1ctx.h.b32,
442                     sizeof(auth_ctx.sha1ctx.h.b32));
443                 break;
444         case CRYPTO_SHA2_256_HMAC:
445                 hmac_init_ipad(&auth_hash_hmac_sha2_256, mkey, mklen,
446                     &auth_ctx);
447                 memcpy(hin, auth_ctx.sha256ctx.state,
448                     sizeof(auth_ctx.sha256ctx.state));
449                 hmac_init_opad(&auth_hash_hmac_sha2_256, mkey, mklen,
450                     &auth_ctx);
451                 memcpy(hout, auth_ctx.sha256ctx.state,
452                     sizeof(auth_ctx.sha256ctx.state));
453                 break;
454         default:
455                 panic("shouldn't get here");
456         }
457
458         for (i = 0; i < CESA_MAX_HASH_LEN / sizeof(uint32_t); i++) {
459                 hin[i] = htobe32(hin[i]);
460                 hout[i] = htobe32(hout[i]);
461         }
462 }
463
464 static int
465 cesa_prep_aes_key(struct cesa_session *cs,
466     const struct crypto_session_params *csp)
467 {
468         uint32_t ek[4 * (RIJNDAEL_MAXNR + 1)];
469         uint32_t *dkey;
470         int i;
471
472         rijndaelKeySetupEnc(ek, cs->cs_key, csp->csp_cipher_klen * 8);
473
474         cs->cs_config &= ~CESA_CSH_AES_KLEN_MASK;
475         dkey = (uint32_t *)cs->cs_aes_dkey;
476
477         switch (csp->csp_cipher_klen) {
478         case 16:
479                 cs->cs_config |= CESA_CSH_AES_KLEN_128;
480                 for (i = 0; i < 4; i++)
481                         *dkey++ = htobe32(ek[4 * 10 + i]);
482                 break;
483         case 24:
484                 cs->cs_config |= CESA_CSH_AES_KLEN_192;
485                 for (i = 0; i < 4; i++)
486                         *dkey++ = htobe32(ek[4 * 12 + i]);
487                 for (i = 0; i < 2; i++)
488                         *dkey++ = htobe32(ek[4 * 11 + 2 + i]);
489                 break;
490         case 32:
491                 cs->cs_config |= CESA_CSH_AES_KLEN_256;
492                 for (i = 0; i < 4; i++)
493                         *dkey++ = htobe32(ek[4 * 14 + i]);
494                 for (i = 0; i < 4; i++)
495                         *dkey++ = htobe32(ek[4 * 13 + i]);
496                 break;
497         default:
498                 return (EINVAL);
499         }
500
501         return (0);
502 }
503
504 static void
505 cesa_start_packet(struct cesa_packet *cp, unsigned int size)
506 {
507
508         cp->cp_size = size;
509         cp->cp_offset = 0;
510         STAILQ_INIT(&cp->cp_copyin);
511         STAILQ_INIT(&cp->cp_copyout);
512 }
513
514 static int
515 cesa_fill_packet(struct cesa_softc *sc, struct cesa_packet *cp,
516     bus_dma_segment_t *seg)
517 {
518         struct cesa_tdma_desc *ctd;
519         unsigned int bsize;
520
521         /* Calculate size of block copy */
522         bsize = MIN(seg->ds_len, cp->cp_size - cp->cp_offset);
523
524         if (bsize > 0) {
525                 ctd = cesa_tdma_copy(sc, sc->sc_sram_base_pa +
526                     CESA_DATA(cp->cp_offset), seg->ds_addr, bsize);
527                 if (!ctd)
528                         return (-ENOMEM);
529
530                 STAILQ_INSERT_TAIL(&cp->cp_copyin, ctd, ctd_stq);
531
532                 ctd = cesa_tdma_copy(sc, seg->ds_addr, sc->sc_sram_base_pa +
533                     CESA_DATA(cp->cp_offset), bsize);
534                 if (!ctd)
535                         return (-ENOMEM);
536
537                 STAILQ_INSERT_TAIL(&cp->cp_copyout, ctd, ctd_stq);
538
539                 seg->ds_len -= bsize;
540                 seg->ds_addr += bsize;
541                 cp->cp_offset += bsize;
542         }
543
544         return (bsize);
545 }
546
547 static void
548 cesa_create_chain_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
549 {
550         unsigned int mpsize, fragmented;
551         unsigned int mlen, mskip, tmlen;
552         struct cesa_chain_info *cci;
553         unsigned int elen, eskip;
554         unsigned int skip, len;
555         struct cesa_sa_desc *csd;
556         struct cesa_request *cr;
557         struct cryptop *crp;
558         struct cesa_softc *sc;
559         struct cesa_packet cp;
560         bus_dma_segment_t seg;
561         uint32_t config;
562         int size;
563
564         cci = arg;
565         sc = cci->cci_sc;
566         cr = cci->cci_cr;
567         crp = cr->cr_crp;
568
569         if (error) {
570                 cci->cci_error = error;
571                 return;
572         }
573
574         /*
575          * Only do a combined op if the AAD is adjacent to the payload
576          * and the AAD length is a multiple of the IV length.  The
577          * checks against 'config' are to avoid recursing when the
578          * logic below invokes separate operations.
579          */
580         config = cci->cci_config;
581         if (((config & CESA_CSHD_OP_MASK) == CESA_CSHD_MAC_AND_ENC ||
582             (config & CESA_CSHD_OP_MASK) == CESA_CSHD_ENC_AND_MAC) &&
583             crp->crp_aad_length != 0 &&
584             (crp->crp_aad_length & (cr->cr_cs->cs_ivlen - 1)) != 0) {
585                 /*
586                  * Data alignment in the request does not meet CESA requiremnts
587                  * for combined encryption/decryption and hashing. We have to
588                  * split the request to separate operations and process them
589                  * one by one.
590                  */
591                 if ((config & CESA_CSHD_OP_MASK) == CESA_CSHD_MAC_AND_ENC) {
592                         config &= ~CESA_CSHD_OP_MASK;
593
594                         cci->cci_config = config | CESA_CSHD_MAC;
595                         cesa_create_chain_cb(cci, segs, nseg, 0);
596
597                         cci->cci_config = config | CESA_CSHD_ENC;
598                         cesa_create_chain_cb(cci, segs, nseg, 0);
599                 } else {
600                         config &= ~CESA_CSHD_OP_MASK;
601
602                         cci->cci_config = config | CESA_CSHD_ENC;
603                         cesa_create_chain_cb(cci, segs, nseg, 0);
604
605                         cci->cci_config = config | CESA_CSHD_MAC;
606                         cesa_create_chain_cb(cci, segs, nseg, 0);
607                 }
608
609                 return;
610         }
611
612         mskip = mlen = eskip = elen = 0;
613
614         if (crp->crp_aad_length == 0) {
615                 skip = crp->crp_payload_start;
616                 len = crp->crp_payload_length;
617                 switch (config & CESA_CSHD_OP_MASK) {
618                 case CESA_CSHD_ENC:
619                         eskip = skip;
620                         elen = len;
621                         break;
622                 case CESA_CSHD_MAC:
623                         mskip = skip;
624                         mlen = len;
625                         break;
626                 default:
627                         eskip = skip;
628                         elen = len;
629                         mskip = skip;
630                         mlen = len;
631                         break;
632                 }
633         } else {
634                 /*
635                  * For an encryption-only separate request, only
636                  * process the payload.  For combined requests and
637                  * hash-only requests, process the entire region.
638                  */
639                 switch (config & CESA_CSHD_OP_MASK) {
640                 case CESA_CSHD_ENC:
641                         skip = crp->crp_payload_start;
642                         len = crp->crp_payload_length;
643                         eskip = skip;
644                         elen = len;
645                         break;
646                 case CESA_CSHD_MAC:
647                         skip = crp->crp_aad_start;
648                         len = crp->crp_aad_length + crp->crp_payload_length;
649                         mskip = skip;
650                         mlen = len;
651                         break;
652                 default:
653                         skip = crp->crp_aad_start;
654                         len = crp->crp_aad_length + crp->crp_payload_length;
655                         mskip = skip;
656                         mlen = len;
657                         eskip = crp->crp_payload_start;
658                         elen = crp->crp_payload_length;
659                         break;
660                 }
661         }
662
663         tmlen = mlen;
664         fragmented = 0;
665         mpsize = CESA_MAX_PACKET_SIZE;
666         mpsize &= ~((cr->cr_cs->cs_ivlen - 1) | (cr->cr_cs->cs_mblen - 1));
667
668         /* Start first packet in chain */
669         cesa_start_packet(&cp, MIN(mpsize, len));
670
671         while (nseg-- && len > 0) {
672                 seg = *(segs++);
673
674                 /*
675                  * Skip data in buffer on which neither ENC nor MAC operation
676                  * is requested.
677                  */
678                 if (skip > 0) {
679                         size = MIN(skip, seg.ds_len);
680                         skip -= size;
681
682                         seg.ds_addr += size;
683                         seg.ds_len -= size;
684
685                         if (eskip > 0)
686                                 eskip -= size;
687
688                         if (mskip > 0)
689                                 mskip -= size;
690
691                         if (seg.ds_len == 0)
692                                 continue;
693                 }
694
695                 while (1) {
696                         /*
697                          * Fill in current packet with data. Break if there is
698                          * no more data in current DMA segment or an error
699                          * occurred.
700                          */
701                         size = cesa_fill_packet(sc, &cp, &seg);
702                         if (size <= 0) {
703                                 error = -size;
704                                 break;
705                         }
706
707                         len -= size;
708
709                         /* If packet is full, append it to the chain */
710                         if (cp.cp_size == cp.cp_offset) {
711                                 csd = cesa_alloc_sdesc(sc, cr);
712                                 if (!csd) {
713                                         error = ENOMEM;
714                                         break;
715                                 }
716
717                                 /* Create SA descriptor for this packet */
718                                 csd->csd_cshd->cshd_config = cci->cci_config;
719                                 csd->csd_cshd->cshd_mac_total_dlen = tmlen;
720
721                                 /*
722                                  * Enable fragmentation if request will not fit
723                                  * into one packet.
724                                  */
725                                 if (len > 0) {
726                                         if (!fragmented) {
727                                                 fragmented = 1;
728                                                 csd->csd_cshd->cshd_config |=
729                                                     CESA_CSHD_FRAG_FIRST;
730                                         } else
731                                                 csd->csd_cshd->cshd_config |=
732                                                     CESA_CSHD_FRAG_MIDDLE;
733                                 } else if (fragmented)
734                                         csd->csd_cshd->cshd_config |=
735                                             CESA_CSHD_FRAG_LAST;
736
737                                 if (eskip < cp.cp_size && elen > 0) {
738                                         csd->csd_cshd->cshd_enc_src =
739                                             CESA_DATA(eskip);
740                                         csd->csd_cshd->cshd_enc_dst =
741                                             CESA_DATA(eskip);
742                                         csd->csd_cshd->cshd_enc_dlen =
743                                             MIN(elen, cp.cp_size - eskip);
744                                 }
745
746                                 if (mskip < cp.cp_size && mlen > 0) {
747                                         csd->csd_cshd->cshd_mac_src =
748                                             CESA_DATA(mskip);
749                                         csd->csd_cshd->cshd_mac_dlen =
750                                             MIN(mlen, cp.cp_size - mskip);
751                                 }
752
753                                 elen -= csd->csd_cshd->cshd_enc_dlen;
754                                 eskip -= MIN(eskip, cp.cp_size);
755                                 mlen -= csd->csd_cshd->cshd_mac_dlen;
756                                 mskip -= MIN(mskip, cp.cp_size);
757
758                                 cesa_dump_cshd(sc, csd->csd_cshd);
759
760                                 /* Append packet to the request */
761                                 error = cesa_append_packet(sc, cr, &cp, csd);
762                                 if (error)
763                                         break;
764
765                                 /* Start a new packet, as current is full */
766                                 cesa_start_packet(&cp, MIN(mpsize, len));
767                         }
768                 }
769
770                 if (error)
771                         break;
772         }
773
774         if (error) {
775                 /*
776                  * Move all allocated resources to the request. They will be
777                  * freed later.
778                  */
779                 STAILQ_CONCAT(&cr->cr_tdesc, &cp.cp_copyin);
780                 STAILQ_CONCAT(&cr->cr_tdesc, &cp.cp_copyout);
781                 cci->cci_error = error;
782         }
783 }
784
785 static int
786 cesa_create_chain(struct cesa_softc *sc,
787     const struct crypto_session_params *csp, struct cesa_request *cr)
788 {
789         struct cesa_chain_info cci;
790         struct cesa_tdma_desc *ctd;
791         uint32_t config;
792         int error;
793
794         error = 0;
795         CESA_LOCK_ASSERT(sc, sessions);
796
797         /* Create request metadata */
798         if (csp->csp_cipher_klen != 0) {
799                 if (csp->csp_cipher_alg == CRYPTO_AES_CBC &&
800                     !CRYPTO_OP_IS_ENCRYPT(cr->cr_crp->crp_op))
801                         memcpy(cr->cr_csd->csd_key, cr->cr_cs->cs_aes_dkey,
802                             csp->csp_cipher_klen);
803                 else
804                         memcpy(cr->cr_csd->csd_key, cr->cr_cs->cs_key,
805                             csp->csp_cipher_klen);
806         }
807
808         if (csp->csp_auth_klen != 0) {
809                 memcpy(cr->cr_csd->csd_hiv_in, cr->cr_cs->cs_hiv_in,
810                     CESA_MAX_HASH_LEN);
811                 memcpy(cr->cr_csd->csd_hiv_out, cr->cr_cs->cs_hiv_out,
812                     CESA_MAX_HASH_LEN);
813         }
814
815         ctd = cesa_tdma_copyin_sa_data(sc, cr);
816         if (!ctd)
817                 return (ENOMEM);
818
819         cesa_append_tdesc(cr, ctd);
820
821         /* Prepare SA configuration */
822         config = cr->cr_cs->cs_config;
823
824         if (csp->csp_cipher_alg != 0 &&
825             !CRYPTO_OP_IS_ENCRYPT(cr->cr_crp->crp_op))
826                 config |= CESA_CSHD_DECRYPT;
827         switch (csp->csp_mode) {
828         case CSP_MODE_CIPHER:
829                 config |= CESA_CSHD_ENC;
830                 break;
831         case CSP_MODE_DIGEST:
832                 config |= CESA_CSHD_MAC;
833                 break;
834         case CSP_MODE_ETA:
835                 config |= (config & CESA_CSHD_DECRYPT) ? CESA_CSHD_MAC_AND_ENC :
836                     CESA_CSHD_ENC_AND_MAC;
837                 break;
838         }
839
840         /* Create data packets */
841         cci.cci_sc = sc;
842         cci.cci_cr = cr;
843         cci.cci_config = config;
844         cci.cci_error = 0;
845
846         error = bus_dmamap_load_crp(sc->sc_data_dtag, cr->cr_dmap, cr->cr_crp,
847             cesa_create_chain_cb, &cci, BUS_DMA_NOWAIT);
848
849         if (!error)
850                 cr->cr_dmap_loaded = 1;
851
852         if (cci.cci_error)
853                 error = cci.cci_error;
854
855         if (error)
856                 return (error);
857
858         /* Read back request metadata */
859         ctd = cesa_tdma_copyout_sa_data(sc, cr);
860         if (!ctd)
861                 return (ENOMEM);
862
863         cesa_append_tdesc(cr, ctd);
864
865         return (0);
866 }
867
868 static void
869 cesa_execute(struct cesa_softc *sc)
870 {
871         struct cesa_tdma_desc *prev_ctd, *ctd;
872         struct cesa_request *prev_cr, *cr;
873
874         CESA_LOCK(sc, requests);
875
876         /*
877          * If ready list is empty, there is nothing to execute. If queued list
878          * is not empty, the hardware is busy and we cannot start another
879          * execution.
880          */
881         if (STAILQ_EMPTY(&sc->sc_ready_requests) ||
882             !STAILQ_EMPTY(&sc->sc_queued_requests)) {
883                 CESA_UNLOCK(sc, requests);
884                 return;
885         }
886
887         /* Move all ready requests to queued list */
888         STAILQ_CONCAT(&sc->sc_queued_requests, &sc->sc_ready_requests);
889         STAILQ_INIT(&sc->sc_ready_requests);
890
891         /* Create one execution chain from all requests on the list */
892         if (STAILQ_FIRST(&sc->sc_queued_requests) !=
893             STAILQ_LAST(&sc->sc_queued_requests, cesa_request, cr_stq)) {
894                 prev_cr = NULL;
895                 cesa_sync_dma_mem(&sc->sc_tdesc_cdm, BUS_DMASYNC_POSTREAD |
896                     BUS_DMASYNC_POSTWRITE);
897
898                 STAILQ_FOREACH(cr, &sc->sc_queued_requests, cr_stq) {
899                         if (prev_cr) {
900                                 ctd = STAILQ_FIRST(&cr->cr_tdesc);
901                                 prev_ctd = STAILQ_LAST(&prev_cr->cr_tdesc,
902                                     cesa_tdma_desc, ctd_stq);
903
904                                 prev_ctd->ctd_cthd->cthd_next =
905                                     ctd->ctd_cthd_paddr;
906                         }
907
908                         prev_cr = cr;
909                 }
910
911                 cesa_sync_dma_mem(&sc->sc_tdesc_cdm, BUS_DMASYNC_PREREAD |
912                     BUS_DMASYNC_PREWRITE);
913         }
914
915         /* Start chain execution in hardware */
916         cr = STAILQ_FIRST(&sc->sc_queued_requests);
917         ctd = STAILQ_FIRST(&cr->cr_tdesc);
918
919         CESA_TDMA_WRITE(sc, CESA_TDMA_ND, ctd->ctd_cthd_paddr);
920
921         if (sc->sc_soc_id == MV_DEV_88F6828 ||
922             sc->sc_soc_id == MV_DEV_88F6820 ||
923             sc->sc_soc_id == MV_DEV_88F6810)
924                 CESA_REG_WRITE(sc, CESA_SA_CMD, CESA_SA_CMD_ACTVATE | CESA_SA_CMD_SHA2);
925         else
926                 CESA_REG_WRITE(sc, CESA_SA_CMD, CESA_SA_CMD_ACTVATE);
927
928         CESA_UNLOCK(sc, requests);
929 }
930
931 static int
932 cesa_setup_sram(struct cesa_softc *sc)
933 {
934         phandle_t sram_node;
935         ihandle_t sram_ihandle;
936         pcell_t sram_handle, sram_reg[2];
937         void *sram_va;
938         int rv;
939
940         rv = OF_getencprop(ofw_bus_get_node(sc->sc_dev), "sram-handle",
941             (void *)&sram_handle, sizeof(sram_handle));
942         if (rv <= 0)
943                 return (rv);
944
945         sram_ihandle = (ihandle_t)sram_handle;
946         sram_node = OF_instance_to_package(sram_ihandle);
947
948         rv = OF_getencprop(sram_node, "reg", (void *)sram_reg, sizeof(sram_reg));
949         if (rv <= 0)
950                 return (rv);
951
952         sc->sc_sram_base_pa = sram_reg[0];
953         /* Store SRAM size to be able to unmap in detach() */
954         sc->sc_sram_size = sram_reg[1];
955
956         if (sc->sc_soc_id != MV_DEV_88F6828 &&
957             sc->sc_soc_id != MV_DEV_88F6820 &&
958             sc->sc_soc_id != MV_DEV_88F6810)
959                 return (0);
960
961         /* SRAM memory was not mapped in platform_sram_devmap(), map it now */
962         sram_va = pmap_mapdev(sc->sc_sram_base_pa, sc->sc_sram_size);
963         if (sram_va == NULL)
964                 return (ENOMEM);
965         sc->sc_sram_base_va = (vm_offset_t)sram_va;
966
967         return (0);
968 }
969
970 /*
971  * Function: device_from_node
972  * This function returns appropriate device_t to phandle_t
973  * Parameters:
974  * root - device where you want to start search
975  *     if you provide NULL here, function will take
976  *     "root0" device as root.
977  * node - we are checking every device_t to be
978  *     appropriate with this.
979  */
980 static device_t
981 device_from_node(device_t root, phandle_t node)
982 {
983         device_t *children, retval;
984         int nkid, i;
985
986         /* Nothing matches no node */
987         if (node == -1)
988                 return (NULL);
989
990         if (root == NULL)
991                 /* Get root of device tree */
992                 if ((root = device_lookup_by_name("root0")) == NULL)
993                         return (NULL);
994
995         if (device_get_children(root, &children, &nkid) != 0)
996                 return (NULL);
997
998         retval = NULL;
999         for (i = 0; i < nkid; i++) {
1000                 /* Check if device and node matches */
1001                 if (OFW_BUS_GET_NODE(root, children[i]) == node) {
1002                         retval = children[i];
1003                         break;
1004                 }
1005                 /* or go deeper */
1006                 if ((retval = device_from_node(children[i], node)) != NULL)
1007                         break;
1008         }
1009         free(children, M_TEMP);
1010
1011         return (retval);
1012 }
1013
1014 static int
1015 cesa_setup_sram_armada(struct cesa_softc *sc)
1016 {
1017         phandle_t sram_node;
1018         ihandle_t sram_ihandle;
1019         pcell_t sram_handle[2];
1020         void *sram_va;
1021         int rv, j;
1022         struct resource_list rl;
1023         struct resource_list_entry *rle;
1024         struct simplebus_softc *ssc;
1025         device_t sdev;
1026
1027         /* Get refs to SRAMS from CESA node */
1028         rv = OF_getencprop(ofw_bus_get_node(sc->sc_dev), "marvell,crypto-srams",
1029             (void *)sram_handle, sizeof(sram_handle));
1030         if (rv <= 0)
1031                 return (rv);
1032
1033         if (sc->sc_cesa_engine_id >= 2)
1034                 return (ENXIO);
1035
1036         /* Get SRAM node on the basis of sc_cesa_engine_id */
1037         sram_ihandle = (ihandle_t)sram_handle[sc->sc_cesa_engine_id];
1038         sram_node = OF_instance_to_package(sram_ihandle);
1039
1040         /* Get device_t of simplebus (sram_node parent) */
1041         sdev = device_from_node(NULL, OF_parent(sram_node));
1042         if (!sdev)
1043                 return (ENXIO);
1044
1045         ssc = device_get_softc(sdev);
1046
1047         resource_list_init(&rl);
1048         /* Parse reg property to resource list */
1049         ofw_bus_reg_to_rl(sdev, sram_node, ssc->acells,
1050             ssc->scells, &rl);
1051
1052         /* We expect only one resource */
1053         rle = resource_list_find(&rl, SYS_RES_MEMORY, 0);
1054         if (rle == NULL)
1055                 return (ENXIO);
1056
1057         /* Remap through ranges property */
1058         for (j = 0; j < ssc->nranges; j++) {
1059                 if (rle->start >= ssc->ranges[j].bus &&
1060                     rle->end < ssc->ranges[j].bus + ssc->ranges[j].size) {
1061                         rle->start -= ssc->ranges[j].bus;
1062                         rle->start += ssc->ranges[j].host;
1063                         rle->end -= ssc->ranges[j].bus;
1064                         rle->end += ssc->ranges[j].host;
1065                 }
1066         }
1067
1068         sc->sc_sram_base_pa = rle->start;
1069         sc->sc_sram_size = rle->count;
1070
1071         /* SRAM memory was not mapped in platform_sram_devmap(), map it now */
1072         sram_va = pmap_mapdev(sc->sc_sram_base_pa, sc->sc_sram_size);
1073         if (sram_va == NULL)
1074                 return (ENOMEM);
1075         sc->sc_sram_base_va = (vm_offset_t)sram_va;
1076
1077         return (0);
1078 }
1079
1080 struct ofw_compat_data cesa_devices[] = {
1081         { "mrvl,cesa", (uintptr_t)true },
1082         { "marvell,armada-38x-crypto", (uintptr_t)true },
1083         { NULL, 0 }
1084 };
1085
1086 static int
1087 cesa_probe(device_t dev)
1088 {
1089
1090         if (!ofw_bus_status_okay(dev))
1091                 return (ENXIO);
1092
1093         if (!ofw_bus_search_compatible(dev, cesa_devices)->ocd_data)
1094                 return (ENXIO);
1095
1096         device_set_desc(dev, "Marvell Cryptographic Engine and Security "
1097             "Accelerator");
1098
1099         return (BUS_PROBE_DEFAULT);
1100 }
1101
1102 static int
1103 cesa_attach(device_t dev)
1104 {
1105         static int engine_idx = 0;
1106         struct simplebus_devinfo *ndi;
1107         struct resource_list *rl;
1108         struct cesa_softc *sc;
1109
1110         if (!ofw_bus_is_compatible(dev, "marvell,armada-38x-crypto"))
1111                 return (cesa_attach_late(dev));
1112
1113         /*
1114          * Get simplebus_devinfo which contains
1115          * resource list filled with adresses and
1116          * interrupts read form FDT.
1117          * Let's correct it by splitting resources
1118          * for each engine.
1119          */
1120         if ((ndi = device_get_ivars(dev)) == NULL)
1121                 return (ENXIO);
1122
1123         rl = &ndi->rl;
1124
1125         switch (engine_idx) {
1126                 case 0:
1127                         /* Update regs values */
1128                         resource_list_add(rl, SYS_RES_MEMORY, 0, CESA0_TDMA_ADDR,
1129                             CESA0_TDMA_ADDR + CESA_TDMA_SIZE - 1, CESA_TDMA_SIZE);
1130                         resource_list_add(rl, SYS_RES_MEMORY, 1, CESA0_CESA_ADDR,
1131                             CESA0_CESA_ADDR + CESA_CESA_SIZE - 1, CESA_CESA_SIZE);
1132
1133                         /* Remove unused interrupt */
1134                         resource_list_delete(rl, SYS_RES_IRQ, 1);
1135                         break;
1136
1137                 case 1:
1138                         /* Update regs values */
1139                         resource_list_add(rl, SYS_RES_MEMORY, 0, CESA1_TDMA_ADDR,
1140                             CESA1_TDMA_ADDR + CESA_TDMA_SIZE - 1, CESA_TDMA_SIZE);
1141                         resource_list_add(rl, SYS_RES_MEMORY, 1, CESA1_CESA_ADDR,
1142                             CESA1_CESA_ADDR + CESA_CESA_SIZE - 1, CESA_CESA_SIZE);
1143
1144                         /* Remove unused interrupt */
1145                         resource_list_delete(rl, SYS_RES_IRQ, 0);
1146                         resource_list_find(rl, SYS_RES_IRQ, 1)->rid = 0;
1147                         break;
1148
1149                 default:
1150                         device_printf(dev, "Bad cesa engine_idx\n");
1151                         return (ENXIO);
1152         }
1153
1154         sc = device_get_softc(dev);
1155         sc->sc_cesa_engine_id = engine_idx;
1156
1157         /*
1158          * Call simplebus_add_device only once.
1159          * It will create second cesa driver instance
1160          * with the same FDT node as first instance.
1161          * When second driver reach this function,
1162          * it will be configured to use second cesa engine
1163          */
1164         if (engine_idx == 0)
1165                 simplebus_add_device(device_get_parent(dev), ofw_bus_get_node(dev),
1166                     0, "cesa", 1, NULL);
1167
1168         engine_idx++;
1169
1170         return (cesa_attach_late(dev));
1171 }
1172
1173 static int
1174 cesa_attach_late(device_t dev)
1175 {
1176         struct cesa_softc *sc;
1177         uint32_t d, r, val;
1178         int error;
1179         int i;
1180
1181         sc = device_get_softc(dev);
1182         sc->sc_blocked = 0;
1183         sc->sc_error = 0;
1184         sc->sc_dev = dev;
1185
1186         soc_id(&d, &r);
1187
1188         switch (d) {
1189         case MV_DEV_88F6281:
1190         case MV_DEV_88F6282:
1191                 /* Check if CESA peripheral device has power turned on */
1192                 if (soc_power_ctrl_get(CPU_PM_CTRL_CRYPTO) ==
1193                     CPU_PM_CTRL_CRYPTO) {
1194                         device_printf(dev, "not powered on\n");
1195                         return (ENXIO);
1196                 }
1197                 sc->sc_tperr = 0;
1198                 break;
1199         case MV_DEV_88F6828:
1200         case MV_DEV_88F6820:
1201         case MV_DEV_88F6810:
1202                 sc->sc_tperr = 0;
1203                 break;
1204         case MV_DEV_MV78100:
1205         case MV_DEV_MV78100_Z0:
1206                 /* Check if CESA peripheral device has power turned on */
1207                 if (soc_power_ctrl_get(CPU_PM_CTRL_CRYPTO) !=
1208                     CPU_PM_CTRL_CRYPTO) {
1209                         device_printf(dev, "not powered on\n");
1210                         return (ENXIO);
1211                 }
1212                 sc->sc_tperr = CESA_ICR_TPERR;
1213                 break;
1214         default:
1215                 return (ENXIO);
1216         }
1217
1218         sc->sc_soc_id = d;
1219
1220         /* Initialize mutexes */
1221         mtx_init(&sc->sc_sc_lock, device_get_nameunit(dev),
1222             "CESA Shared Data", MTX_DEF);
1223         mtx_init(&sc->sc_tdesc_lock, device_get_nameunit(dev),
1224             "CESA TDMA Descriptors Pool", MTX_DEF);
1225         mtx_init(&sc->sc_sdesc_lock, device_get_nameunit(dev),
1226             "CESA SA Descriptors Pool", MTX_DEF);
1227         mtx_init(&sc->sc_requests_lock, device_get_nameunit(dev),
1228             "CESA Requests Pool", MTX_DEF);
1229         mtx_init(&sc->sc_sessions_lock, device_get_nameunit(dev),
1230             "CESA Sessions Pool", MTX_DEF);
1231
1232         /* Allocate I/O and IRQ resources */
1233         error = bus_alloc_resources(dev, cesa_res_spec, sc->sc_res);
1234         if (error) {
1235                 device_printf(dev, "could not allocate resources\n");
1236                 goto err0;
1237         }
1238
1239         /* Acquire SRAM base address */
1240         if (!ofw_bus_is_compatible(dev, "marvell,armada-38x-crypto"))
1241                 error = cesa_setup_sram(sc);
1242         else
1243                 error = cesa_setup_sram_armada(sc);
1244
1245         if (error) {
1246                 device_printf(dev, "could not setup SRAM\n");
1247                 goto err1;
1248         }
1249
1250         /* Setup interrupt handler */
1251         error = bus_setup_intr(dev, sc->sc_res[RES_CESA_IRQ], INTR_TYPE_NET |
1252             INTR_MPSAFE, NULL, cesa_intr, sc, &(sc->sc_icookie));
1253         if (error) {
1254                 device_printf(dev, "could not setup engine completion irq\n");
1255                 goto err2;
1256         }
1257
1258         /* Create DMA tag for processed data */
1259         error = bus_dma_tag_create(bus_get_dma_tag(dev),        /* parent */
1260             1, 0,                               /* alignment, boundary */
1261             BUS_SPACE_MAXADDR_32BIT,            /* lowaddr */
1262             BUS_SPACE_MAXADDR,                  /* highaddr */
1263             NULL, NULL,                         /* filtfunc, filtfuncarg */
1264             CESA_MAX_REQUEST_SIZE,              /* maxsize */
1265             CESA_MAX_FRAGMENTS,                 /* nsegments */
1266             CESA_MAX_REQUEST_SIZE, 0,           /* maxsegsz, flags */
1267             NULL, NULL,                         /* lockfunc, lockfuncarg */
1268             &sc->sc_data_dtag);                 /* dmat */
1269         if (error)
1270                 goto err3;
1271
1272         /* Initialize data structures: TDMA Descriptors Pool */
1273         error = cesa_alloc_dma_mem(sc, &sc->sc_tdesc_cdm,
1274             CESA_TDMA_DESCRIPTORS * sizeof(struct cesa_tdma_hdesc));
1275         if (error)
1276                 goto err4;
1277
1278         STAILQ_INIT(&sc->sc_free_tdesc);
1279         for (i = 0; i < CESA_TDMA_DESCRIPTORS; i++) {
1280                 sc->sc_tdesc[i].ctd_cthd =
1281                     (struct cesa_tdma_hdesc *)(sc->sc_tdesc_cdm.cdm_vaddr) + i;
1282                 sc->sc_tdesc[i].ctd_cthd_paddr = sc->sc_tdesc_cdm.cdm_paddr +
1283                     (i * sizeof(struct cesa_tdma_hdesc));
1284                 STAILQ_INSERT_TAIL(&sc->sc_free_tdesc, &sc->sc_tdesc[i],
1285                     ctd_stq);
1286         }
1287
1288         /* Initialize data structures: SA Descriptors Pool */
1289         error = cesa_alloc_dma_mem(sc, &sc->sc_sdesc_cdm,
1290             CESA_SA_DESCRIPTORS * sizeof(struct cesa_sa_hdesc));
1291         if (error)
1292                 goto err5;
1293
1294         STAILQ_INIT(&sc->sc_free_sdesc);
1295         for (i = 0; i < CESA_SA_DESCRIPTORS; i++) {
1296                 sc->sc_sdesc[i].csd_cshd =
1297                     (struct cesa_sa_hdesc *)(sc->sc_sdesc_cdm.cdm_vaddr) + i;
1298                 sc->sc_sdesc[i].csd_cshd_paddr = sc->sc_sdesc_cdm.cdm_paddr +
1299                     (i * sizeof(struct cesa_sa_hdesc));
1300                 STAILQ_INSERT_TAIL(&sc->sc_free_sdesc, &sc->sc_sdesc[i],
1301                     csd_stq);
1302         }
1303
1304         /* Initialize data structures: Requests Pool */
1305         error = cesa_alloc_dma_mem(sc, &sc->sc_requests_cdm,
1306             CESA_REQUESTS * sizeof(struct cesa_sa_data));
1307         if (error)
1308                 goto err6;
1309
1310         STAILQ_INIT(&sc->sc_free_requests);
1311         STAILQ_INIT(&sc->sc_ready_requests);
1312         STAILQ_INIT(&sc->sc_queued_requests);
1313         for (i = 0; i < CESA_REQUESTS; i++) {
1314                 sc->sc_requests[i].cr_csd =
1315                     (struct cesa_sa_data *)(sc->sc_requests_cdm.cdm_vaddr) + i;
1316                 sc->sc_requests[i].cr_csd_paddr =
1317                     sc->sc_requests_cdm.cdm_paddr +
1318                     (i * sizeof(struct cesa_sa_data));
1319
1320                 /* Preallocate DMA maps */
1321                 error = bus_dmamap_create(sc->sc_data_dtag, 0,
1322                     &sc->sc_requests[i].cr_dmap);
1323                 if (error && i > 0) {
1324                         i--;
1325                         do {
1326                                 bus_dmamap_destroy(sc->sc_data_dtag,
1327                                     sc->sc_requests[i].cr_dmap);
1328                         } while (i--);
1329
1330                         goto err7;
1331                 }
1332
1333                 STAILQ_INSERT_TAIL(&sc->sc_free_requests, &sc->sc_requests[i],
1334                     cr_stq);
1335         }
1336
1337         /*
1338          * Initialize TDMA:
1339          * - Burst limit: 128 bytes,
1340          * - Outstanding reads enabled,
1341          * - No byte-swap.
1342          */
1343         val = CESA_TDMA_CR_DBL128 | CESA_TDMA_CR_SBL128 |
1344             CESA_TDMA_CR_ORDEN | CESA_TDMA_CR_NBS | CESA_TDMA_CR_ENABLE;
1345
1346         if (sc->sc_soc_id == MV_DEV_88F6828 ||
1347             sc->sc_soc_id == MV_DEV_88F6820 ||
1348             sc->sc_soc_id == MV_DEV_88F6810)
1349                 val |= CESA_TDMA_NUM_OUTSTAND;
1350
1351         CESA_TDMA_WRITE(sc, CESA_TDMA_CR, val);
1352
1353         /*
1354          * Initialize SA:
1355          * - SA descriptor is present at beginning of CESA SRAM,
1356          * - Multi-packet chain mode,
1357          * - Cooperation with TDMA enabled.
1358          */
1359         CESA_REG_WRITE(sc, CESA_SA_DPR, 0);
1360         CESA_REG_WRITE(sc, CESA_SA_CR, CESA_SA_CR_ACTIVATE_TDMA |
1361             CESA_SA_CR_WAIT_FOR_TDMA | CESA_SA_CR_MULTI_MODE);
1362
1363         /* Unmask interrupts */
1364         CESA_REG_WRITE(sc, CESA_ICR, 0);
1365         CESA_REG_WRITE(sc, CESA_ICM, CESA_ICM_ACCTDMA | sc->sc_tperr);
1366         CESA_TDMA_WRITE(sc, CESA_TDMA_ECR, 0);
1367         CESA_TDMA_WRITE(sc, CESA_TDMA_EMR, CESA_TDMA_EMR_MISS |
1368             CESA_TDMA_EMR_DOUBLE_HIT | CESA_TDMA_EMR_BOTH_HIT |
1369             CESA_TDMA_EMR_DATA_ERROR);
1370
1371         /* Register in OCF */
1372         sc->sc_cid = crypto_get_driverid(dev, sizeof(struct cesa_session),
1373             CRYPTOCAP_F_HARDWARE);
1374         if (sc->sc_cid < 0) {
1375                 device_printf(dev, "could not get crypto driver id\n");
1376                 goto err8;
1377         }
1378
1379         return (0);
1380 err8:
1381         for (i = 0; i < CESA_REQUESTS; i++)
1382                 bus_dmamap_destroy(sc->sc_data_dtag,
1383                     sc->sc_requests[i].cr_dmap);
1384 err7:
1385         cesa_free_dma_mem(&sc->sc_requests_cdm);
1386 err6:
1387         cesa_free_dma_mem(&sc->sc_sdesc_cdm);
1388 err5:
1389         cesa_free_dma_mem(&sc->sc_tdesc_cdm);
1390 err4:
1391         bus_dma_tag_destroy(sc->sc_data_dtag);
1392 err3:
1393         bus_teardown_intr(dev, sc->sc_res[RES_CESA_IRQ], sc->sc_icookie);
1394 err2:
1395         if (sc->sc_soc_id == MV_DEV_88F6828 ||
1396             sc->sc_soc_id == MV_DEV_88F6820 ||
1397             sc->sc_soc_id == MV_DEV_88F6810)
1398                 pmap_unmapdev(sc->sc_sram_base_va, sc->sc_sram_size);
1399 err1:
1400         bus_release_resources(dev, cesa_res_spec, sc->sc_res);
1401 err0:
1402         mtx_destroy(&sc->sc_sessions_lock);
1403         mtx_destroy(&sc->sc_requests_lock);
1404         mtx_destroy(&sc->sc_sdesc_lock);
1405         mtx_destroy(&sc->sc_tdesc_lock);
1406         mtx_destroy(&sc->sc_sc_lock);
1407         return (ENXIO);
1408 }
1409
1410 static int
1411 cesa_detach(device_t dev)
1412 {
1413         struct cesa_softc *sc;
1414         int i;
1415  
1416         sc = device_get_softc(dev);
1417
1418         /* TODO: Wait for queued requests completion before shutdown. */
1419
1420         /* Mask interrupts */
1421         CESA_REG_WRITE(sc, CESA_ICM, 0);
1422         CESA_TDMA_WRITE(sc, CESA_TDMA_EMR, 0);
1423
1424         /* Unregister from OCF */
1425         crypto_unregister_all(sc->sc_cid);
1426
1427         /* Free DMA Maps */
1428         for (i = 0; i < CESA_REQUESTS; i++)
1429                 bus_dmamap_destroy(sc->sc_data_dtag,
1430                     sc->sc_requests[i].cr_dmap);
1431
1432         /* Free DMA Memory */
1433         cesa_free_dma_mem(&sc->sc_requests_cdm);
1434         cesa_free_dma_mem(&sc->sc_sdesc_cdm);
1435         cesa_free_dma_mem(&sc->sc_tdesc_cdm);
1436
1437         /* Free DMA Tag */
1438         bus_dma_tag_destroy(sc->sc_data_dtag);
1439
1440         /* Stop interrupt */
1441         bus_teardown_intr(dev, sc->sc_res[RES_CESA_IRQ], sc->sc_icookie);
1442
1443         /* Relase I/O and IRQ resources */
1444         bus_release_resources(dev, cesa_res_spec, sc->sc_res);
1445
1446         /* Unmap SRAM memory */
1447         if (sc->sc_soc_id == MV_DEV_88F6828 ||
1448             sc->sc_soc_id == MV_DEV_88F6820 ||
1449             sc->sc_soc_id == MV_DEV_88F6810)
1450                 pmap_unmapdev(sc->sc_sram_base_va, sc->sc_sram_size);
1451
1452         /* Destroy mutexes */
1453         mtx_destroy(&sc->sc_sessions_lock);
1454         mtx_destroy(&sc->sc_requests_lock);
1455         mtx_destroy(&sc->sc_sdesc_lock);
1456         mtx_destroy(&sc->sc_tdesc_lock);
1457         mtx_destroy(&sc->sc_sc_lock);
1458
1459         return (0);
1460 }
1461
1462 static void
1463 cesa_intr(void *arg)
1464 {
1465         STAILQ_HEAD(, cesa_request) requests;
1466         struct cesa_request *cr, *tmp;
1467         struct cesa_softc *sc;
1468         uint32_t ecr, icr;
1469         uint8_t hash[HASH_MAX_LEN];
1470         int blocked;
1471
1472         sc = arg;
1473
1474         /* Ack interrupt */
1475         ecr = CESA_TDMA_READ(sc, CESA_TDMA_ECR);
1476         CESA_TDMA_WRITE(sc, CESA_TDMA_ECR, 0);
1477         icr = CESA_REG_READ(sc, CESA_ICR);
1478         CESA_REG_WRITE(sc, CESA_ICR, 0);
1479
1480         /* Check for TDMA errors */
1481         if (ecr & CESA_TDMA_ECR_MISS) {
1482                 device_printf(sc->sc_dev, "TDMA Miss error detected!\n");
1483                 sc->sc_error = EIO;
1484         }
1485
1486         if (ecr & CESA_TDMA_ECR_DOUBLE_HIT) {
1487                 device_printf(sc->sc_dev, "TDMA Double Hit error detected!\n");
1488                 sc->sc_error = EIO;
1489         }
1490
1491         if (ecr & CESA_TDMA_ECR_BOTH_HIT) {
1492                 device_printf(sc->sc_dev, "TDMA Both Hit error detected!\n");
1493                 sc->sc_error = EIO;
1494         }
1495
1496         if (ecr & CESA_TDMA_ECR_DATA_ERROR) {
1497                 device_printf(sc->sc_dev, "TDMA Data error detected!\n");
1498                 sc->sc_error = EIO;
1499         }
1500
1501         /* Check for CESA errors */
1502         if (icr & sc->sc_tperr) {
1503                 device_printf(sc->sc_dev, "CESA SRAM Parity error detected!\n");
1504                 sc->sc_error = EIO;
1505         }
1506
1507         /* If there is nothing more to do, return */
1508         if ((icr & CESA_ICR_ACCTDMA) == 0)
1509                 return;
1510
1511         /* Get all finished requests */
1512         CESA_LOCK(sc, requests);
1513         STAILQ_INIT(&requests);
1514         STAILQ_CONCAT(&requests, &sc->sc_queued_requests);
1515         STAILQ_INIT(&sc->sc_queued_requests);
1516         CESA_UNLOCK(sc, requests);
1517
1518         /* Execute all ready requests */
1519         cesa_execute(sc);
1520
1521         /* Process completed requests */
1522         cesa_sync_dma_mem(&sc->sc_requests_cdm, BUS_DMASYNC_POSTREAD |
1523             BUS_DMASYNC_POSTWRITE);
1524
1525         STAILQ_FOREACH_SAFE(cr, &requests, cr_stq, tmp) {
1526                 bus_dmamap_sync(sc->sc_data_dtag, cr->cr_dmap,
1527                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1528
1529                 cr->cr_crp->crp_etype = sc->sc_error;
1530                 if (cr->cr_cs->cs_hlen != 0 && cr->cr_crp->crp_etype == 0) {
1531                         if (cr->cr_crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
1532                                 crypto_copydata(cr->cr_crp,
1533                                     cr->cr_crp->crp_digest_start,
1534                                     cr->cr_cs->cs_hlen, hash);
1535                                 if (timingsafe_bcmp(hash, cr->cr_csd->csd_hash,
1536                                     cr->cr_cs->cs_hlen) != 0)
1537                                         cr->cr_crp->crp_etype = EBADMSG;
1538                         } else
1539                                 crypto_copyback(cr->cr_crp,
1540                                     cr->cr_crp->crp_digest_start,
1541                                     cr->cr_cs->cs_hlen, cr->cr_csd->csd_hash);
1542                 }
1543                 crypto_done(cr->cr_crp);
1544                 cesa_free_request(sc, cr);
1545         }
1546
1547         cesa_sync_dma_mem(&sc->sc_requests_cdm, BUS_DMASYNC_PREREAD |
1548             BUS_DMASYNC_PREWRITE);
1549
1550         sc->sc_error = 0;
1551
1552         /* Unblock driver if it ran out of resources */
1553         CESA_LOCK(sc, sc);
1554         blocked = sc->sc_blocked;
1555         sc->sc_blocked = 0;
1556         CESA_UNLOCK(sc, sc);
1557
1558         if (blocked)
1559                 crypto_unblock(sc->sc_cid, blocked);
1560 }
1561
1562 static bool
1563 cesa_cipher_supported(const struct crypto_session_params *csp)
1564 {
1565
1566         switch (csp->csp_cipher_alg) {
1567         case CRYPTO_AES_CBC:
1568                 if (csp->csp_ivlen != AES_BLOCK_LEN)
1569                         return (false);
1570                 break;
1571         default:
1572                 return (false);
1573         }
1574
1575         if (csp->csp_cipher_klen > CESA_MAX_KEY_LEN)
1576                 return (false);
1577
1578         return (true);
1579 }
1580
1581 static bool
1582 cesa_auth_supported(struct cesa_softc *sc,
1583     const struct crypto_session_params *csp)
1584 {
1585
1586         switch (csp->csp_auth_alg) {
1587         case CRYPTO_SHA2_256_HMAC:
1588                 if (!(sc->sc_soc_id == MV_DEV_88F6828 ||
1589                     sc->sc_soc_id == MV_DEV_88F6820 ||
1590                     sc->sc_soc_id == MV_DEV_88F6810))
1591                         return (false);
1592                 /* FALLTHROUGH */
1593         case CRYPTO_SHA1:
1594         case CRYPTO_SHA1_HMAC:
1595                 break;
1596         default:
1597                 return (false);
1598         }
1599
1600         if (csp->csp_auth_klen > CESA_MAX_MKEY_LEN)
1601                 return (false);
1602
1603         return (true);
1604 }
1605
1606 static int
1607 cesa_probesession(device_t dev, const struct crypto_session_params *csp)
1608 {
1609         struct cesa_softc *sc;
1610
1611         sc = device_get_softc(dev);
1612         if (csp->csp_flags != 0)
1613                 return (EINVAL);
1614         switch (csp->csp_mode) {
1615         case CSP_MODE_DIGEST:
1616                 if (!cesa_auth_supported(sc, csp))
1617                         return (EINVAL);
1618                 break;
1619         case CSP_MODE_CIPHER:
1620                 if (!cesa_cipher_supported(csp))
1621                         return (EINVAL);
1622                 break;
1623         case CSP_MODE_ETA:
1624                 if (!cesa_auth_supported(sc, csp) ||
1625                     !cesa_cipher_supported(csp))
1626                         return (EINVAL);
1627                 break;
1628         default:
1629                 return (EINVAL);
1630         }
1631         return (CRYPTODEV_PROBE_HARDWARE);
1632 }
1633
1634 static int
1635 cesa_newsession(device_t dev, crypto_session_t cses,
1636     const struct crypto_session_params *csp)
1637 {
1638         struct cesa_session *cs;
1639         struct cesa_softc *sc;
1640         int error;
1641  
1642         sc = device_get_softc(dev);
1643         error = 0;
1644
1645         /* Allocate session */
1646         cs = crypto_get_driver_session(cses);
1647
1648         /* Prepare CESA configuration */
1649         cs->cs_config = 0;
1650         cs->cs_ivlen = 1;
1651         cs->cs_mblen = 1;
1652
1653         switch (csp->csp_cipher_alg) {
1654         case CRYPTO_AES_CBC:
1655                 cs->cs_config |= CESA_CSHD_AES | CESA_CSHD_CBC;
1656                 cs->cs_ivlen = AES_BLOCK_LEN;
1657                 break;
1658         }
1659
1660         switch (csp->csp_auth_alg) {
1661         case CRYPTO_SHA1:
1662                 cs->cs_mblen = 1;
1663                 cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA1_HASH_LEN :
1664                     csp->csp_auth_mlen;
1665                 cs->cs_config |= CESA_CSHD_SHA1;
1666                 break;
1667         case CRYPTO_SHA1_HMAC:
1668                 cs->cs_mblen = SHA1_BLOCK_LEN;
1669                 cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA1_HASH_LEN :
1670                     csp->csp_auth_mlen;
1671                 cs->cs_config |= CESA_CSHD_SHA1_HMAC;
1672                 if (cs->cs_hlen == CESA_HMAC_TRUNC_LEN)
1673                         cs->cs_config |= CESA_CSHD_96_BIT_HMAC;
1674                 break;
1675         case CRYPTO_SHA2_256_HMAC:
1676                 cs->cs_mblen = SHA2_256_BLOCK_LEN;
1677                 cs->cs_hlen = (csp->csp_auth_mlen == 0) ? SHA2_256_HASH_LEN :
1678                     csp->csp_auth_mlen;
1679                 cs->cs_config |= CESA_CSHD_SHA2_256_HMAC;
1680                 break;
1681         }
1682
1683         /* Save cipher key */
1684         if (csp->csp_cipher_key != NULL) {
1685                 memcpy(cs->cs_key, csp->csp_cipher_key,
1686                     csp->csp_cipher_klen);
1687                 if (csp->csp_cipher_alg == CRYPTO_AES_CBC)
1688                         error = cesa_prep_aes_key(cs, csp);
1689         }
1690
1691         /* Save digest key */
1692         if (csp->csp_auth_key != NULL)
1693                 cesa_set_mkey(cs, csp->csp_auth_alg, csp->csp_auth_key,
1694                     csp->csp_auth_klen);
1695
1696         return (error);
1697 }
1698
1699 static int
1700 cesa_process(device_t dev, struct cryptop *crp, int hint)
1701 {
1702         const struct crypto_session_params *csp;
1703         struct cesa_request *cr;
1704         struct cesa_session *cs;
1705         struct cesa_softc *sc;
1706         int error;
1707
1708         sc = device_get_softc(dev);
1709         error = 0;
1710
1711         cs = crypto_get_driver_session(crp->crp_session);
1712         csp = crypto_get_params(crp->crp_session);
1713
1714         /* Check and parse input */
1715         if (crp->crp_ilen > CESA_MAX_REQUEST_SIZE) {
1716                 crp->crp_etype = E2BIG;
1717                 crypto_done(crp);
1718                 return (0);
1719         }
1720
1721         /*
1722          * For requests with AAD, only requests where the AAD is
1723          * immediately adjacent to the payload are supported.
1724          */
1725         if (crp->crp_aad_length != 0 &&
1726             (crp->crp_aad_start + crp->crp_aad_length) !=
1727             crp->crp_payload_start) {
1728                 crp->crp_etype = EINVAL;
1729                 crypto_done(crp);
1730                 return (0);
1731         }
1732
1733         /*
1734          * Get request descriptor. Block driver if there is no free
1735          * descriptors in pool.
1736          */
1737         cr = cesa_alloc_request(sc);
1738         if (!cr) {
1739                 CESA_LOCK(sc, sc);
1740                 sc->sc_blocked = CRYPTO_SYMQ;
1741                 CESA_UNLOCK(sc, sc);
1742                 return (ERESTART);
1743         }
1744
1745         /* Prepare request */
1746         cr->cr_crp = crp;
1747         cr->cr_cs = cs;
1748
1749         CESA_LOCK(sc, sessions);
1750         cesa_sync_desc(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1751
1752         if (csp->csp_cipher_alg != 0)
1753                 crypto_read_iv(crp, cr->cr_csd->csd_iv);
1754
1755         if (crp->crp_cipher_key != NULL) {
1756                 memcpy(cs->cs_key, crp->crp_cipher_key,
1757                     csp->csp_cipher_klen);
1758                 if (csp->csp_cipher_alg == CRYPTO_AES_CBC)
1759                         error = cesa_prep_aes_key(cs, csp);
1760         }
1761
1762         if (!error && crp->crp_auth_key != NULL)
1763                 cesa_set_mkey(cs, csp->csp_auth_alg, crp->crp_auth_key,
1764                     csp->csp_auth_klen);
1765
1766         /* Convert request to chain of TDMA and SA descriptors */
1767         if (!error)
1768                 error = cesa_create_chain(sc, csp, cr);
1769
1770         cesa_sync_desc(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1771         CESA_UNLOCK(sc, sessions);
1772
1773         if (error) {
1774                 cesa_free_request(sc, cr);
1775                 crp->crp_etype = error;
1776                 crypto_done(crp);
1777                 return (0);
1778         }
1779
1780         bus_dmamap_sync(sc->sc_data_dtag, cr->cr_dmap, BUS_DMASYNC_PREREAD |
1781             BUS_DMASYNC_PREWRITE);
1782
1783         /* Enqueue request to execution */
1784         cesa_enqueue_request(sc, cr);
1785
1786         /* Start execution, if we have no more requests in queue */
1787         if ((hint & CRYPTO_HINT_MORE) == 0)
1788                 cesa_execute(sc);
1789
1790         return (0);
1791 }