crypto: mv_cesa - Support processing of data from previous requests
[firefly-linux-kernel-4.4.55.git] / drivers / crypto / mv_cesa.c
1 /*
2  * Support for Marvell's crypto engine which can be found on some Orion5X
3  * boards.
4  *
5  * Author: Sebastian Andrzej Siewior < sebastian at breakpoint dot cc >
6  * License: GPLv2
7  *
8  */
9 #include <crypto/aes.h>
10 #include <crypto/algapi.h>
11 #include <linux/crypto.h>
12 #include <linux/interrupt.h>
13 #include <linux/io.h>
14 #include <linux/kthread.h>
15 #include <linux/platform_device.h>
16 #include <linux/scatterlist.h>
17
18 #include "mv_cesa.h"
19 /*
20  * STM:
21  *   /---------------------------------------\
22  *   |                                       | request complete
23  *  \./                                      |
24  * IDLE -> new request -> BUSY -> done -> DEQUEUE
25  *                         /°\               |
26  *                          |                | more scatter entries
27  *                          \________________/
28  */
29 enum engine_status {
30         ENGINE_IDLE,
31         ENGINE_BUSY,
32         ENGINE_W_DEQUEUE,
33 };
34
35 /**
36  * struct req_progress - used for every crypt request
37  * @src_sg_it:          sg iterator for src
38  * @dst_sg_it:          sg iterator for dst
39  * @sg_src_left:        bytes left in src to process (scatter list)
40  * @src_start:          offset to add to src start position (scatter list)
41  * @crypt_len:          length of current crypt process
42  * @hw_nbytes:          total bytes to process in hw for this request
43  * @copy_back:          whether to copy data back (crypt) or not (hash)
44  * @sg_dst_left:        bytes left dst to process in this scatter list
45  * @dst_start:          offset to add to dst start position (scatter list)
46  * @hw_processed_bytes: number of bytes processed by hw (request).
47  *
48  * sg helper are used to iterate over the scatterlist. Since the size of the
49  * SRAM may be less than the scatter size, this struct struct is used to keep
50  * track of progress within current scatterlist.
51  */
52 struct req_progress {
53         struct sg_mapping_iter src_sg_it;
54         struct sg_mapping_iter dst_sg_it;
55         void (*complete) (void);
56         void (*process) (int is_first);
57
58         /* src mostly */
59         int sg_src_left;
60         int src_start;
61         int crypt_len;
62         int hw_nbytes;
63         /* dst mostly */
64         int copy_back;
65         int sg_dst_left;
66         int dst_start;
67         int hw_processed_bytes;
68 };
69
70 struct crypto_priv {
71         void __iomem *reg;
72         void __iomem *sram;
73         int irq;
74         struct task_struct *queue_th;
75
76         /* the lock protects queue and eng_st */
77         spinlock_t lock;
78         struct crypto_queue queue;
79         enum engine_status eng_st;
80         struct crypto_async_request *cur_req;
81         struct req_progress p;
82         int max_req_size;
83         int sram_size;
84 };
85
86 static struct crypto_priv *cpg;
87
88 struct mv_ctx {
89         u8 aes_enc_key[AES_KEY_LEN];
90         u32 aes_dec_key[8];
91         int key_len;
92         u32 need_calc_aes_dkey;
93 };
94
95 enum crypto_op {
96         COP_AES_ECB,
97         COP_AES_CBC,
98 };
99
100 struct mv_req_ctx {
101         enum crypto_op op;
102         int decrypt;
103 };
104
105 static void compute_aes_dec_key(struct mv_ctx *ctx)
106 {
107         struct crypto_aes_ctx gen_aes_key;
108         int key_pos;
109
110         if (!ctx->need_calc_aes_dkey)
111                 return;
112
113         crypto_aes_expand_key(&gen_aes_key, ctx->aes_enc_key, ctx->key_len);
114
115         key_pos = ctx->key_len + 24;
116         memcpy(ctx->aes_dec_key, &gen_aes_key.key_enc[key_pos], 4 * 4);
117         switch (ctx->key_len) {
118         case AES_KEYSIZE_256:
119                 key_pos -= 2;
120                 /* fall */
121         case AES_KEYSIZE_192:
122                 key_pos -= 2;
123                 memcpy(&ctx->aes_dec_key[4], &gen_aes_key.key_enc[key_pos],
124                                 4 * 4);
125                 break;
126         }
127         ctx->need_calc_aes_dkey = 0;
128 }
129
130 static int mv_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
131                 unsigned int len)
132 {
133         struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
134         struct mv_ctx *ctx = crypto_tfm_ctx(tfm);
135
136         switch (len) {
137         case AES_KEYSIZE_128:
138         case AES_KEYSIZE_192:
139         case AES_KEYSIZE_256:
140                 break;
141         default:
142                 crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
143                 return -EINVAL;
144         }
145         ctx->key_len = len;
146         ctx->need_calc_aes_dkey = 1;
147
148         memcpy(ctx->aes_enc_key, key, AES_KEY_LEN);
149         return 0;
150 }
151
152 static void copy_src_to_buf(struct req_progress *p, char *dbuf, int len)
153 {
154         int ret;
155         void *sbuf;
156         int copied = 0;
157
158         while (1) {
159                 if (!p->sg_src_left) {
160                         ret = sg_miter_next(&p->src_sg_it);
161                         BUG_ON(!ret);
162                         p->sg_src_left = p->src_sg_it.length;
163                         p->src_start = 0;
164                 }
165
166                 sbuf = p->src_sg_it.addr + p->src_start;
167
168                 if (p->sg_src_left <= len - copied) {
169                         memcpy(dbuf + copied, sbuf, p->sg_src_left);
170                         copied += p->sg_src_left;
171                         p->sg_src_left = 0;
172                         if (copied >= len)
173                                 break;
174                 } else {
175                         int copy_len = len - copied;
176                         memcpy(dbuf + copied, sbuf, copy_len);
177                         p->src_start += copy_len;
178                         p->sg_src_left -= copy_len;
179                         break;
180                 }
181         }
182 }
183
184 static void setup_data_in(void)
185 {
186         struct req_progress *p = &cpg->p;
187         int data_in_sram =
188             min(p->hw_nbytes - p->hw_processed_bytes, cpg->max_req_size);
189         copy_src_to_buf(p, cpg->sram + SRAM_DATA_IN_START + p->crypt_len,
190                         data_in_sram - p->crypt_len);
191         p->crypt_len = data_in_sram;
192 }
193
194 static void mv_process_current_q(int first_block)
195 {
196         struct ablkcipher_request *req = ablkcipher_request_cast(cpg->cur_req);
197         struct mv_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
198         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
199         struct sec_accel_config op;
200
201         switch (req_ctx->op) {
202         case COP_AES_ECB:
203                 op.config = CFG_OP_CRYPT_ONLY | CFG_ENCM_AES | CFG_ENC_MODE_ECB;
204                 break;
205         case COP_AES_CBC:
206         default:
207                 op.config = CFG_OP_CRYPT_ONLY | CFG_ENCM_AES | CFG_ENC_MODE_CBC;
208                 op.enc_iv = ENC_IV_POINT(SRAM_DATA_IV) |
209                         ENC_IV_BUF_POINT(SRAM_DATA_IV_BUF);
210                 if (first_block)
211                         memcpy(cpg->sram + SRAM_DATA_IV, req->info, 16);
212                 break;
213         }
214         if (req_ctx->decrypt) {
215                 op.config |= CFG_DIR_DEC;
216                 memcpy(cpg->sram + SRAM_DATA_KEY_P, ctx->aes_dec_key,
217                                 AES_KEY_LEN);
218         } else {
219                 op.config |= CFG_DIR_ENC;
220                 memcpy(cpg->sram + SRAM_DATA_KEY_P, ctx->aes_enc_key,
221                                 AES_KEY_LEN);
222         }
223
224         switch (ctx->key_len) {
225         case AES_KEYSIZE_128:
226                 op.config |= CFG_AES_LEN_128;
227                 break;
228         case AES_KEYSIZE_192:
229                 op.config |= CFG_AES_LEN_192;
230                 break;
231         case AES_KEYSIZE_256:
232                 op.config |= CFG_AES_LEN_256;
233                 break;
234         }
235         op.enc_p = ENC_P_SRC(SRAM_DATA_IN_START) |
236                 ENC_P_DST(SRAM_DATA_OUT_START);
237         op.enc_key_p = SRAM_DATA_KEY_P;
238
239         setup_data_in();
240         op.enc_len = cpg->p.crypt_len;
241         memcpy(cpg->sram + SRAM_CONFIG, &op,
242                         sizeof(struct sec_accel_config));
243
244         writel(SRAM_CONFIG, cpg->reg + SEC_ACCEL_DESC_P0);
245         /* GO */
246         writel(SEC_CMD_EN_SEC_ACCL0, cpg->reg + SEC_ACCEL_CMD);
247
248         /*
249          * XXX: add timer if the interrupt does not occur for some mystery
250          * reason
251          */
252 }
253
254 static void mv_crypto_algo_completion(void)
255 {
256         struct ablkcipher_request *req = ablkcipher_request_cast(cpg->cur_req);
257         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
258
259         sg_miter_stop(&cpg->p.src_sg_it);
260         sg_miter_stop(&cpg->p.dst_sg_it);
261
262         if (req_ctx->op != COP_AES_CBC)
263                 return ;
264
265         memcpy(req->info, cpg->sram + SRAM_DATA_IV_BUF, 16);
266 }
267
268 static void dequeue_complete_req(void)
269 {
270         struct crypto_async_request *req = cpg->cur_req;
271         void *buf;
272         int ret;
273         cpg->p.hw_processed_bytes += cpg->p.crypt_len;
274         if (cpg->p.copy_back) {
275                 int need_copy_len = cpg->p.crypt_len;
276                 int sram_offset = 0;
277                 do {
278                         int dst_copy;
279
280                         if (!cpg->p.sg_dst_left) {
281                                 ret = sg_miter_next(&cpg->p.dst_sg_it);
282                                 BUG_ON(!ret);
283                                 cpg->p.sg_dst_left = cpg->p.dst_sg_it.length;
284                                 cpg->p.dst_start = 0;
285                         }
286
287                         buf = cpg->p.dst_sg_it.addr;
288                         buf += cpg->p.dst_start;
289
290                         dst_copy = min(need_copy_len, cpg->p.sg_dst_left);
291
292                         memcpy(buf,
293                                cpg->sram + SRAM_DATA_OUT_START + sram_offset,
294                                dst_copy);
295                         sram_offset += dst_copy;
296                         cpg->p.sg_dst_left -= dst_copy;
297                         need_copy_len -= dst_copy;
298                         cpg->p.dst_start += dst_copy;
299                 } while (need_copy_len > 0);
300         }
301
302         cpg->p.crypt_len = 0;
303
304         BUG_ON(cpg->eng_st != ENGINE_W_DEQUEUE);
305         if (cpg->p.hw_processed_bytes < cpg->p.hw_nbytes) {
306                 /* process next scatter list entry */
307                 cpg->eng_st = ENGINE_BUSY;
308                 cpg->p.process(0);
309         } else {
310                 cpg->p.complete();
311                 cpg->eng_st = ENGINE_IDLE;
312                 local_bh_disable();
313                 req->complete(req, 0);
314                 local_bh_enable();
315         }
316 }
317
318 static int count_sgs(struct scatterlist *sl, unsigned int total_bytes)
319 {
320         int i = 0;
321         size_t cur_len;
322
323         while (1) {
324                 cur_len = sl[i].length;
325                 ++i;
326                 if (total_bytes > cur_len)
327                         total_bytes -= cur_len;
328                 else
329                         break;
330         }
331
332         return i;
333 }
334
335 static void mv_enqueue_new_req(struct ablkcipher_request *req)
336 {
337         struct req_progress *p = &cpg->p;
338         int num_sgs;
339
340         cpg->cur_req = &req->base;
341         memset(p, 0, sizeof(struct req_progress));
342         p->hw_nbytes = req->nbytes;
343         p->complete = mv_crypto_algo_completion;
344         p->process = mv_process_current_q;
345         p->copy_back = 1;
346
347         num_sgs = count_sgs(req->src, req->nbytes);
348         sg_miter_start(&p->src_sg_it, req->src, num_sgs, SG_MITER_FROM_SG);
349
350         num_sgs = count_sgs(req->dst, req->nbytes);
351         sg_miter_start(&p->dst_sg_it, req->dst, num_sgs, SG_MITER_TO_SG);
352
353         mv_process_current_q(1);
354 }
355
356 static int queue_manag(void *data)
357 {
358         cpg->eng_st = ENGINE_IDLE;
359         do {
360                 struct ablkcipher_request *req;
361                 struct crypto_async_request *async_req = NULL;
362                 struct crypto_async_request *backlog;
363
364                 __set_current_state(TASK_INTERRUPTIBLE);
365
366                 if (cpg->eng_st == ENGINE_W_DEQUEUE)
367                         dequeue_complete_req();
368
369                 spin_lock_irq(&cpg->lock);
370                 if (cpg->eng_st == ENGINE_IDLE) {
371                         backlog = crypto_get_backlog(&cpg->queue);
372                         async_req = crypto_dequeue_request(&cpg->queue);
373                         if (async_req) {
374                                 BUG_ON(cpg->eng_st != ENGINE_IDLE);
375                                 cpg->eng_st = ENGINE_BUSY;
376                         }
377                 }
378                 spin_unlock_irq(&cpg->lock);
379
380                 if (backlog) {
381                         backlog->complete(backlog, -EINPROGRESS);
382                         backlog = NULL;
383                 }
384
385                 if (async_req) {
386                         req = container_of(async_req,
387                                         struct ablkcipher_request, base);
388                         mv_enqueue_new_req(req);
389                         async_req = NULL;
390                 }
391
392                 schedule();
393
394         } while (!kthread_should_stop());
395         return 0;
396 }
397
398 static int mv_handle_req(struct crypto_async_request *req)
399 {
400         unsigned long flags;
401         int ret;
402
403         spin_lock_irqsave(&cpg->lock, flags);
404         ret = crypto_enqueue_request(&cpg->queue, req);
405         spin_unlock_irqrestore(&cpg->lock, flags);
406         wake_up_process(cpg->queue_th);
407         return ret;
408 }
409
410 static int mv_enc_aes_ecb(struct ablkcipher_request *req)
411 {
412         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
413
414         req_ctx->op = COP_AES_ECB;
415         req_ctx->decrypt = 0;
416
417         return mv_handle_req(&req->base);
418 }
419
420 static int mv_dec_aes_ecb(struct ablkcipher_request *req)
421 {
422         struct mv_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
423         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
424
425         req_ctx->op = COP_AES_ECB;
426         req_ctx->decrypt = 1;
427
428         compute_aes_dec_key(ctx);
429         return mv_handle_req(&req->base);
430 }
431
432 static int mv_enc_aes_cbc(struct ablkcipher_request *req)
433 {
434         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
435
436         req_ctx->op = COP_AES_CBC;
437         req_ctx->decrypt = 0;
438
439         return mv_handle_req(&req->base);
440 }
441
442 static int mv_dec_aes_cbc(struct ablkcipher_request *req)
443 {
444         struct mv_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
445         struct mv_req_ctx *req_ctx = ablkcipher_request_ctx(req);
446
447         req_ctx->op = COP_AES_CBC;
448         req_ctx->decrypt = 1;
449
450         compute_aes_dec_key(ctx);
451         return mv_handle_req(&req->base);
452 }
453
454 static int mv_cra_init(struct crypto_tfm *tfm)
455 {
456         tfm->crt_ablkcipher.reqsize = sizeof(struct mv_req_ctx);
457         return 0;
458 }
459
460 irqreturn_t crypto_int(int irq, void *priv)
461 {
462         u32 val;
463
464         val = readl(cpg->reg + SEC_ACCEL_INT_STATUS);
465         if (!(val & SEC_INT_ACCEL0_DONE))
466                 return IRQ_NONE;
467
468         val &= ~SEC_INT_ACCEL0_DONE;
469         writel(val, cpg->reg + FPGA_INT_STATUS);
470         writel(val, cpg->reg + SEC_ACCEL_INT_STATUS);
471         BUG_ON(cpg->eng_st != ENGINE_BUSY);
472         cpg->eng_st = ENGINE_W_DEQUEUE;
473         wake_up_process(cpg->queue_th);
474         return IRQ_HANDLED;
475 }
476
477 struct crypto_alg mv_aes_alg_ecb = {
478         .cra_name               = "ecb(aes)",
479         .cra_driver_name        = "mv-ecb-aes",
480         .cra_priority   = 300,
481         .cra_flags      = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
482         .cra_blocksize  = 16,
483         .cra_ctxsize    = sizeof(struct mv_ctx),
484         .cra_alignmask  = 0,
485         .cra_type       = &crypto_ablkcipher_type,
486         .cra_module     = THIS_MODULE,
487         .cra_init       = mv_cra_init,
488         .cra_u          = {
489                 .ablkcipher = {
490                         .min_keysize    =       AES_MIN_KEY_SIZE,
491                         .max_keysize    =       AES_MAX_KEY_SIZE,
492                         .setkey         =       mv_setkey_aes,
493                         .encrypt        =       mv_enc_aes_ecb,
494                         .decrypt        =       mv_dec_aes_ecb,
495                 },
496         },
497 };
498
499 struct crypto_alg mv_aes_alg_cbc = {
500         .cra_name               = "cbc(aes)",
501         .cra_driver_name        = "mv-cbc-aes",
502         .cra_priority   = 300,
503         .cra_flags      = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
504         .cra_blocksize  = AES_BLOCK_SIZE,
505         .cra_ctxsize    = sizeof(struct mv_ctx),
506         .cra_alignmask  = 0,
507         .cra_type       = &crypto_ablkcipher_type,
508         .cra_module     = THIS_MODULE,
509         .cra_init       = mv_cra_init,
510         .cra_u          = {
511                 .ablkcipher = {
512                         .ivsize         =       AES_BLOCK_SIZE,
513                         .min_keysize    =       AES_MIN_KEY_SIZE,
514                         .max_keysize    =       AES_MAX_KEY_SIZE,
515                         .setkey         =       mv_setkey_aes,
516                         .encrypt        =       mv_enc_aes_cbc,
517                         .decrypt        =       mv_dec_aes_cbc,
518                 },
519         },
520 };
521
522 static int mv_probe(struct platform_device *pdev)
523 {
524         struct crypto_priv *cp;
525         struct resource *res;
526         int irq;
527         int ret;
528
529         if (cpg) {
530                 printk(KERN_ERR "Second crypto dev?\n");
531                 return -EEXIST;
532         }
533
534         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
535         if (!res)
536                 return -ENXIO;
537
538         cp = kzalloc(sizeof(*cp), GFP_KERNEL);
539         if (!cp)
540                 return -ENOMEM;
541
542         spin_lock_init(&cp->lock);
543         crypto_init_queue(&cp->queue, 50);
544         cp->reg = ioremap(res->start, res->end - res->start + 1);
545         if (!cp->reg) {
546                 ret = -ENOMEM;
547                 goto err;
548         }
549
550         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
551         if (!res) {
552                 ret = -ENXIO;
553                 goto err_unmap_reg;
554         }
555         cp->sram_size = res->end - res->start + 1;
556         cp->max_req_size = cp->sram_size - SRAM_CFG_SPACE;
557         cp->sram = ioremap(res->start, cp->sram_size);
558         if (!cp->sram) {
559                 ret = -ENOMEM;
560                 goto err_unmap_reg;
561         }
562
563         irq = platform_get_irq(pdev, 0);
564         if (irq < 0 || irq == NO_IRQ) {
565                 ret = irq;
566                 goto err_unmap_sram;
567         }
568         cp->irq = irq;
569
570         platform_set_drvdata(pdev, cp);
571         cpg = cp;
572
573         cp->queue_th = kthread_run(queue_manag, cp, "mv_crypto");
574         if (IS_ERR(cp->queue_th)) {
575                 ret = PTR_ERR(cp->queue_th);
576                 goto err_thread;
577         }
578
579         ret = request_irq(irq, crypto_int, IRQF_DISABLED, dev_name(&pdev->dev),
580                         cp);
581         if (ret)
582                 goto err_unmap_sram;
583
584         writel(SEC_INT_ACCEL0_DONE, cpg->reg + SEC_ACCEL_INT_MASK);
585         writel(SEC_CFG_STOP_DIG_ERR, cpg->reg + SEC_ACCEL_CFG);
586
587         ret = crypto_register_alg(&mv_aes_alg_ecb);
588         if (ret)
589                 goto err_reg;
590
591         ret = crypto_register_alg(&mv_aes_alg_cbc);
592         if (ret)
593                 goto err_unreg_ecb;
594         return 0;
595 err_unreg_ecb:
596         crypto_unregister_alg(&mv_aes_alg_ecb);
597 err_thread:
598         free_irq(irq, cp);
599 err_reg:
600         kthread_stop(cp->queue_th);
601 err_unmap_sram:
602         iounmap(cp->sram);
603 err_unmap_reg:
604         iounmap(cp->reg);
605 err:
606         kfree(cp);
607         cpg = NULL;
608         platform_set_drvdata(pdev, NULL);
609         return ret;
610 }
611
612 static int mv_remove(struct platform_device *pdev)
613 {
614         struct crypto_priv *cp = platform_get_drvdata(pdev);
615
616         crypto_unregister_alg(&mv_aes_alg_ecb);
617         crypto_unregister_alg(&mv_aes_alg_cbc);
618         kthread_stop(cp->queue_th);
619         free_irq(cp->irq, cp);
620         memset(cp->sram, 0, cp->sram_size);
621         iounmap(cp->sram);
622         iounmap(cp->reg);
623         kfree(cp);
624         cpg = NULL;
625         return 0;
626 }
627
628 static struct platform_driver marvell_crypto = {
629         .probe          = mv_probe,
630         .remove         = mv_remove,
631         .driver         = {
632                 .owner  = THIS_MODULE,
633                 .name   = "mv_crypto",
634         },
635 };
636 MODULE_ALIAS("platform:mv_crypto");
637
638 static int __init mv_crypto_init(void)
639 {
640         return platform_driver_register(&marvell_crypto);
641 }
642 module_init(mv_crypto_init);
643
644 static void __exit mv_crypto_exit(void)
645 {
646         platform_driver_unregister(&marvell_crypto);
647 }
648 module_exit(mv_crypto_exit);
649
650 MODULE_AUTHOR("Sebastian Andrzej Siewior <sebastian@breakpoint.cc>");
651 MODULE_DESCRIPTION("Support for Marvell's cryptographic engine");
652 MODULE_LICENSE("GPL");