ocf: update to version 20120127
[openwrt/svn-archive/archive.git] / target / linux / generic / files / crypto / ocf / kirkwood / cesa_ocf_drv.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms. Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12
13 ********************************************************************************
14 Marvell GPL License Option
15
16 If you received this File from Marvell, you may opt to use, redistribute and/or
17 modify this File in accordance with the terms and conditions of the General
18 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
19 available along with the File in the license.txt file or by writing to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
21 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
22
23 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
24 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
25 DISCLAIMED. The GPL License provides additional details about this warranty
26 disclaimer.
27 *******************************************************************************/
28
29 #include <linux/version.h>
30 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
31 #include <linux/config.h>
32 #endif
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/list.h>
36 #include <linux/slab.h>
37 #include <linux/sched.h>
38 #include <linux/wait.h>
39 #include <linux/crypto.h>
40 #include <linux/mm.h>
41 #include <linux/skbuff.h>
42 #include <linux/random.h>
43 #include <linux/platform_device.h>
44 #include <asm/scatterlist.h>
45 #include <linux/spinlock.h>
46 #include "ctrlEnv/sys/mvSysCesa.h"
47 #include "cesa/mvCesa.h" /* moved here before cryptodev.h due to include dependencies */
48 #include <cryptodev.h>
49 #include <uio.h>
50 #include <plat/mv_cesa.h>
51 #include <linux/mbus.h>
52 #include "mvDebug.h"
53
54 #include "cesa/mvMD5.h"
55 #include "cesa/mvSHA1.h"
56
57 #include "cesa/mvCesaRegs.h"
58 #include "cesa/AES/mvAes.h"
59 #include "cesa/mvLru.h"
60
61 #undef RT_DEBUG
62 #ifdef RT_DEBUG
63 static int debug = 1;
64 module_param(debug, int, 1);
65 MODULE_PARM_DESC(debug, "Enable debug");
66 #undef dprintk
67 #define dprintk(a...) if (debug) { printk(a); } else
68 #else
69 static int debug = 0;
70 #undef dprintk
71 #define dprintk(a...)
72 #endif
73
74
75 /* TDMA Regs */
76 #define WINDOW_BASE(i) 0xA00 + (i << 3)
77 #define WINDOW_CTRL(i) 0xA04 + (i << 3)
78
79 /* interrupt handling */
80 #undef CESA_OCF_POLLING
81 #undef CESA_OCF_TASKLET
82
83 #if defined(CESA_OCF_POLLING) && defined(CESA_OCF_TASKLET)
84 #error "don't use both tasklet and polling mode"
85 #endif
86
87 extern int cesaReqResources;
88 /* support for spliting action into 2 actions */
89 #define CESA_OCF_SPLIT
90
91 /* general defines */
92 #define CESA_OCF_MAX_SES 128
93 #define CESA_Q_SIZE 64
94
95 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
96 #define FRAG_PAGE(f) (f).p
97 #else
98 #define FRAG_PAGE(f) (f)
99 #endif
100
101 /* data structures */
102 struct cesa_ocf_data {
103 int cipher_alg;
104 int auth_alg;
105 int encrypt_tn_auth;
106 #define auth_tn_decrypt encrypt_tn_auth
107 int ivlen;
108 int digestlen;
109 short sid_encrypt;
110 short sid_decrypt;
111 /* fragment workaround sessions */
112 short frag_wa_encrypt;
113 short frag_wa_decrypt;
114 short frag_wa_auth;
115 };
116
117 /* CESA device data */
118 struct cesa_dev {
119 void __iomem *sram;
120 void __iomem *reg;
121 struct mv_cesa_platform_data *plat_data;
122 int irq;
123 };
124
125 #define DIGEST_BUF_SIZE 32
126 struct cesa_ocf_process {
127 MV_CESA_COMMAND cesa_cmd;
128 MV_CESA_MBUF cesa_mbuf;
129 MV_BUF_INFO cesa_bufs[MV_CESA_MAX_MBUF_FRAGS];
130 char digest[DIGEST_BUF_SIZE];
131 int digest_len;
132 struct cryptop *crp;
133 int need_cb;
134 };
135
136 /* global variables */
137 static int32_t cesa_ocf_id = -1;
138 static struct cesa_ocf_data *cesa_ocf_sessions[CESA_OCF_MAX_SES];
139 static spinlock_t cesa_lock;
140 static struct cesa_dev cesa_device;
141
142 /* static APIs */
143 static int cesa_ocf_process (device_t, struct cryptop *, int);
144 static int cesa_ocf_newsession (device_t, u_int32_t *, struct cryptoini *);
145 static int cesa_ocf_freesession (device_t, u_int64_t);
146 static void cesa_callback (unsigned long);
147 static irqreturn_t cesa_interrupt_handler (int, void *);
148 #ifdef CESA_OCF_POLLING
149 static void cesa_interrupt_polling(void);
150 #endif
151 #ifdef CESA_OCF_TASKLET
152 static struct tasklet_struct cesa_ocf_tasklet;
153 #endif
154
155 static struct timeval tt_start;
156 static struct timeval tt_end;
157
158 /*
159 * dummy device structure
160 */
161
162 static struct {
163 softc_device_decl sc_dev;
164 } mv_cesa_dev;
165
166 static device_method_t mv_cesa_methods = {
167 /* crypto device methods */
168 DEVMETHOD(cryptodev_newsession, cesa_ocf_newsession),
169 DEVMETHOD(cryptodev_freesession,cesa_ocf_freesession),
170 DEVMETHOD(cryptodev_process, cesa_ocf_process),
171 DEVMETHOD(cryptodev_kprocess, NULL),
172 };
173
174
175
176 /* Add debug Trace */
177 #undef CESA_OCF_TRACE_DEBUG
178 #ifdef CESA_OCF_TRACE_DEBUG
179
180 #define MV_CESA_USE_TIMER_ID 0
181
182 typedef struct
183 {
184 int type; /* 0 - isrEmpty, 1 - cesaReadyGet, 2 - cesaAction */
185 MV_U32 timeStamp;
186 MV_U32 cause;
187 MV_U32 realCause;
188 MV_U32 dmaCause;
189 int resources;
190 MV_CESA_REQ* pReqReady;
191 MV_CESA_REQ* pReqEmpty;
192 MV_CESA_REQ* pReqProcess;
193 } MV_CESA_TEST_TRACE;
194
195 #define MV_CESA_TEST_TRACE_SIZE 50
196
197 static int cesaTestTraceIdx = 0;
198 static MV_CESA_TEST_TRACE cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
199
200 static void cesaTestTraceAdd(int type)
201 {
202 cesaTestTrace[cesaTestTraceIdx].type = type;
203 cesaTestTrace[cesaTestTraceIdx].realCause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
204 //cesaTestTrace[cesaTestTraceIdx].idmaCause = MV_REG_READ(IDMA_CAUSE_REG);
205 cesaTestTrace[cesaTestTraceIdx].resources = cesaReqResources;
206 cesaTestTrace[cesaTestTraceIdx].pReqReady = pCesaReqReady;
207 cesaTestTrace[cesaTestTraceIdx].pReqEmpty = pCesaReqEmpty;
208 cesaTestTrace[cesaTestTraceIdx].pReqProcess = pCesaReqProcess;
209 cesaTestTrace[cesaTestTraceIdx].timeStamp = mvCntmrRead(MV_CESA_USE_TIMER_ID);
210 cesaTestTraceIdx++;
211 if(cesaTestTraceIdx == MV_CESA_TEST_TRACE_SIZE)
212 cesaTestTraceIdx = 0;
213 }
214
215 #else /* CESA_OCF_TRACE_DEBUG */
216
217 #define cesaTestTraceAdd(x)
218
219 #endif /* CESA_OCF_TRACE_DEBUG */
220
221 unsigned int
222 get_usec(unsigned int start)
223 {
224 if(start) {
225 do_gettimeofday (&tt_start);
226 return 0;
227 }
228 else {
229 do_gettimeofday (&tt_end);
230 tt_end.tv_sec -= tt_start.tv_sec;
231 tt_end.tv_usec -= tt_start.tv_usec;
232 if (tt_end.tv_usec < 0) {
233 tt_end.tv_usec += 1000 * 1000;
234 tt_end.tv_sec -= 1;
235 }
236 }
237 printk("time taken is %d\n", (unsigned int)(tt_end.tv_usec + tt_end.tv_sec * 1000000));
238 return (tt_end.tv_usec + tt_end.tv_sec * 1000000);
239 }
240
241 #ifdef RT_DEBUG
242 /*
243 * check that the crp action match the current session
244 */
245 static int
246 ocf_check_action(struct cryptop *crp, struct cesa_ocf_data *cesa_ocf_cur_ses) {
247 int count = 0;
248 int encrypt = 0, decrypt = 0, auth = 0;
249 struct cryptodesc *crd;
250
251 /* Go through crypto descriptors, processing as we go */
252 for (crd = crp->crp_desc; crd; crd = crd->crd_next, count++) {
253 if(count > 2) {
254 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
255 return 1;
256 }
257
258 /* Encryption /Decryption */
259 if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
260 /* check that the action is compatible with session */
261 if(encrypt || decrypt) {
262 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
263 return 1;
264 }
265
266 if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
267 if( (count == 2) && (cesa_ocf_cur_ses->encrypt_tn_auth) ) {
268 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
269 return 1;
270 }
271 encrypt++;
272 }
273 else { /* decrypt */
274 if( (count == 2) && !(cesa_ocf_cur_ses->auth_tn_decrypt) ) {
275 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
276 return 1;
277 }
278 decrypt++;
279 }
280
281 }
282 /* Authentication */
283 else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
284 /* check that the action is compatible with session */
285 if(auth) {
286 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
287 return 1;
288 }
289 if( (count == 2) && (decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
290 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
291 return 1;
292 }
293 if( (count == 2) && (encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)) {
294 printk("%s,%d: sequence isn't supported by this session.\n", __FILE__, __LINE__);
295 return 1;
296 }
297 auth++;
298 }
299 else {
300 printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
301 return 1;
302 }
303 }
304 return 0;
305
306 }
307 #endif
308
309 /*
310 * Process a request.
311 */
312 static int
313 cesa_ocf_process(device_t dev, struct cryptop *crp, int hint)
314 {
315 struct cesa_ocf_process *cesa_ocf_cmd = NULL;
316 struct cesa_ocf_process *cesa_ocf_cmd_wa = NULL;
317 MV_CESA_COMMAND *cesa_cmd;
318 struct cryptodesc *crd;
319 struct cesa_ocf_data *cesa_ocf_cur_ses;
320 int sid = 0, temp_len = 0, i;
321 int encrypt = 0, decrypt = 0, auth = 0;
322 int status;
323 struct sk_buff *skb = NULL;
324 struct uio *uiop = NULL;
325 unsigned char *ivp;
326 MV_BUF_INFO *p_buf_info;
327 MV_CESA_MBUF *p_mbuf_info;
328 unsigned long flags;
329
330 dprintk("%s()\n", __FUNCTION__);
331
332 if( cesaReqResources <= 1 ) {
333 dprintk("%s,%d: ERESTART\n", __FILE__, __LINE__);
334 return ERESTART;
335 }
336
337 #ifdef RT_DEBUG
338 /* Sanity check */
339 if (crp == NULL) {
340 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
341 return EINVAL;
342 }
343
344 if (crp->crp_desc == NULL || crp->crp_buf == NULL ) {
345 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
346 crp->crp_etype = EINVAL;
347 return EINVAL;
348 }
349
350 sid = crp->crp_sid & 0xffffffff;
351 if ((sid >= CESA_OCF_MAX_SES) || (cesa_ocf_sessions[sid] == NULL)) {
352 crp->crp_etype = ENOENT;
353 printk("%s,%d: ENOENT session %d \n", __FILE__, __LINE__, sid);
354 return EINVAL;
355 }
356 #endif
357
358 sid = crp->crp_sid & 0xffffffff;
359 crp->crp_etype = 0;
360 cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
361
362 #ifdef RT_DEBUG
363 if(ocf_check_action(crp, cesa_ocf_cur_ses)){
364 goto p_error;
365 }
366 #endif
367
368 /* malloc a new cesa process */
369 cesa_ocf_cmd = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
370
371 if (cesa_ocf_cmd == NULL) {
372 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
373 goto p_error;
374 }
375 memset(cesa_ocf_cmd, 0, sizeof(struct cesa_ocf_process));
376
377 /* init cesa_process */
378 cesa_ocf_cmd->crp = crp;
379 /* always call callback */
380 cesa_ocf_cmd->need_cb = 1;
381
382 /* init cesa_cmd for usage of the HALs */
383 cesa_cmd = &cesa_ocf_cmd->cesa_cmd;
384 cesa_cmd->pReqPrv = (void *)cesa_ocf_cmd;
385 cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_encrypt; /* defualt use encrypt */
386
387 /* prepare src buffer */
388 /* we send the entire buffer to the HAL, even if only part of it should be encrypt/auth. */
389 /* if not using seesions for both encrypt and auth, then it will be wiser to to copy only */
390 /* from skip to crd_len. */
391 p_buf_info = cesa_ocf_cmd->cesa_bufs;
392 p_mbuf_info = &cesa_ocf_cmd->cesa_mbuf;
393
394 p_buf_info += 2; /* save 2 first buffers for IV and digest -
395 we won't append them to the end since, they
396 might be places in an unaligned addresses. */
397
398 p_mbuf_info->pFrags = p_buf_info;
399 temp_len = 0;
400
401 /* handle SKB */
402 if (crp->crp_flags & CRYPTO_F_SKBUF) {
403
404 dprintk("%s,%d: handle SKB.\n", __FILE__, __LINE__);
405 skb = (struct sk_buff *) crp->crp_buf;
406
407 if (skb_shinfo(skb)->nr_frags >= (MV_CESA_MAX_MBUF_FRAGS - 1)) {
408 printk("%s,%d: %d nr_frags > MV_CESA_MAX_MBUF_FRAGS", __FILE__, __LINE__, skb_shinfo(skb)->nr_frags);
409 goto p_error;
410 }
411
412 p_mbuf_info->mbufSize = skb->len;
413 temp_len = skb->len;
414 /* first skb fragment */
415 p_buf_info->bufSize = skb_headlen(skb);
416 p_buf_info->bufVirtPtr = skb->data;
417 p_buf_info++;
418
419 /* now handle all other skb fragments */
420 for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ ) {
421 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
422 p_buf_info->bufSize = frag->size;
423 p_buf_info->bufVirtPtr = page_address(FRAG_PAGE(frag->page)) + frag->page_offset;
424 p_buf_info++;
425 }
426 p_mbuf_info->numFrags = skb_shinfo(skb)->nr_frags + 1;
427 }
428 /* handle UIO */
429 else if(crp->crp_flags & CRYPTO_F_IOV) {
430
431 dprintk("%s,%d: handle UIO.\n", __FILE__, __LINE__);
432 uiop = (struct uio *) crp->crp_buf;
433
434 if (uiop->uio_iovcnt > (MV_CESA_MAX_MBUF_FRAGS - 1)) {
435 printk("%s,%d: %d uio_iovcnt > MV_CESA_MAX_MBUF_FRAGS \n", __FILE__, __LINE__, uiop->uio_iovcnt);
436 goto p_error;
437 }
438
439 p_mbuf_info->mbufSize = crp->crp_ilen;
440 p_mbuf_info->numFrags = uiop->uio_iovcnt;
441 for(i = 0; i < uiop->uio_iovcnt; i++) {
442 p_buf_info->bufVirtPtr = uiop->uio_iov[i].iov_base;
443 p_buf_info->bufSize = uiop->uio_iov[i].iov_len;
444 temp_len += p_buf_info->bufSize;
445 dprintk("%s,%d: buf %x-> addr %x, size %x \n"
446 , __FILE__, __LINE__, i, (unsigned int)p_buf_info->bufVirtPtr, p_buf_info->bufSize);
447 p_buf_info++;
448 }
449
450 }
451 /* handle CONTIG */
452 else {
453 dprintk("%s,%d: handle CONTIG.\n", __FILE__, __LINE__);
454 p_mbuf_info->numFrags = 1;
455 p_mbuf_info->mbufSize = crp->crp_ilen;
456 p_buf_info->bufVirtPtr = crp->crp_buf;
457 p_buf_info->bufSize = crp->crp_ilen;
458 temp_len = crp->crp_ilen;
459 p_buf_info++;
460 }
461
462 /* Support up to 64K why? cause! */
463 if(crp->crp_ilen > 64*1024) {
464 printk("%s,%d: buf too big %x \n", __FILE__, __LINE__, crp->crp_ilen);
465 goto p_error;
466 }
467
468 if( temp_len != crp->crp_ilen ) {
469 printk("%s,%d: warning size don't match.(%x %x) \n", __FILE__, __LINE__, temp_len, crp->crp_ilen);
470 }
471
472 cesa_cmd->pSrc = p_mbuf_info;
473 cesa_cmd->pDst = p_mbuf_info;
474
475 /* restore p_buf_info to point to first available buf */
476 p_buf_info = cesa_ocf_cmd->cesa_bufs;
477 p_buf_info += 1;
478
479
480 /* Go through crypto descriptors, processing as we go */
481 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
482
483 /* Encryption /Decryption */
484 if(crd->crd_alg == cesa_ocf_cur_ses->cipher_alg) {
485
486 dprintk("%s,%d: cipher", __FILE__, __LINE__);
487
488 cesa_cmd->cryptoOffset = crd->crd_skip;
489 cesa_cmd->cryptoLength = crd->crd_len;
490
491 if(crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
492 dprintk(" encrypt \n");
493 encrypt++;
494
495 /* handle IV */
496 if (crd->crd_flags & CRD_F_IV_EXPLICIT) { /* IV from USER */
497 dprintk("%s,%d: IV from USER (offset %x) \n", __FILE__, __LINE__, crd->crd_inject);
498 cesa_cmd->ivFromUser = 1;
499 ivp = crd->crd_iv;
500
501 /*
502 * do we have to copy the IV back to the buffer ?
503 */
504 if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
505 dprintk("%s,%d: copy the IV back to the buffer\n", __FILE__, __LINE__);
506 cesa_cmd->ivOffset = crd->crd_inject;
507 crypto_copyback(crp->crp_flags, crp->crp_buf, crd->crd_inject, cesa_ocf_cur_ses->ivlen, ivp);
508 }
509 else {
510 dprintk("%s,%d: don't copy the IV back to the buffer \n", __FILE__, __LINE__);
511 p_mbuf_info->numFrags++;
512 p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen;
513 p_mbuf_info->pFrags = p_buf_info;
514
515 p_buf_info->bufVirtPtr = ivp;
516 p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen;
517 p_buf_info--;
518
519 /* offsets */
520 cesa_cmd->ivOffset = 0;
521 cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
522 if(auth) {
523 cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
524 cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen;
525 }
526 }
527 }
528 else { /* random IV */
529 dprintk("%s,%d: random IV \n", __FILE__, __LINE__);
530 cesa_cmd->ivFromUser = 0;
531
532 /*
533 * do we have to copy the IV back to the buffer ?
534 */
535 /* in this mode the HAL will always copy the IV */
536 /* given by the session to the ivOffset */
537 if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
538 cesa_cmd->ivOffset = crd->crd_inject;
539 }
540 else {
541 /* if IV isn't copy, then how will the user know which IV did we use??? */
542 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
543 goto p_error;
544 }
545 }
546 }
547 else { /* decrypt */
548 dprintk(" decrypt \n");
549 decrypt++;
550 cesa_cmd->sessionId = cesa_ocf_cur_ses->sid_decrypt;
551
552 /* handle IV */
553 if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
554 dprintk("%s,%d: IV from USER \n", __FILE__, __LINE__);
555 /* append the IV buf to the mbuf */
556 cesa_cmd->ivFromUser = 1;
557 p_mbuf_info->numFrags++;
558 p_mbuf_info->mbufSize += cesa_ocf_cur_ses->ivlen;
559 p_mbuf_info->pFrags = p_buf_info;
560
561 p_buf_info->bufVirtPtr = crd->crd_iv;
562 p_buf_info->bufSize = cesa_ocf_cur_ses->ivlen;
563 p_buf_info--;
564
565 /* offsets */
566 cesa_cmd->ivOffset = 0;
567 cesa_cmd->cryptoOffset += cesa_ocf_cur_ses->ivlen;
568 if(auth) {
569 cesa_cmd->macOffset += cesa_ocf_cur_ses->ivlen;
570 cesa_cmd->digestOffset += cesa_ocf_cur_ses->ivlen;
571 }
572 }
573 else {
574 dprintk("%s,%d: IV inside the buffer \n", __FILE__, __LINE__);
575 cesa_cmd->ivFromUser = 0;
576 cesa_cmd->ivOffset = crd->crd_inject;
577 }
578 }
579
580 }
581 /* Authentication */
582 else if(crd->crd_alg == cesa_ocf_cur_ses->auth_alg) {
583 dprintk("%s,%d: Authentication \n", __FILE__, __LINE__);
584 auth++;
585 cesa_cmd->macOffset = crd->crd_skip;
586 cesa_cmd->macLength = crd->crd_len;
587
588 /* digest + mac */
589 cesa_cmd->digestOffset = crd->crd_inject;
590 }
591 else {
592 printk("%s,%d: Alg isn't supported by this session.\n", __FILE__, __LINE__);
593 goto p_error;
594 }
595 }
596
597 dprintk("\n");
598 dprintk("%s,%d: Sending Action: \n", __FILE__, __LINE__);
599 dprintk("%s,%d: IV from user: %d. IV offset %x \n", __FILE__, __LINE__, cesa_cmd->ivFromUser, cesa_cmd->ivOffset);
600 dprintk("%s,%d: crypt offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->cryptoOffset, cesa_cmd->cryptoLength);
601 dprintk("%s,%d: Auth offset %x len %x \n", __FILE__, __LINE__, cesa_cmd->macOffset, cesa_cmd->macLength);
602 dprintk("%s,%d: set digest in offset %x . \n", __FILE__, __LINE__, cesa_cmd->digestOffset);
603 if(debug) {
604 mvCesaDebugMbuf("SRC BUFFER", cesa_cmd->pSrc, 0, cesa_cmd->pSrc->mbufSize);
605 }
606
607
608 /* send action to HAL */
609 spin_lock_irqsave(&cesa_lock, flags);
610 status = mvCesaAction(cesa_cmd);
611 spin_unlock_irqrestore(&cesa_lock, flags);
612
613 /* action not allowed */
614 if(status == MV_NOT_ALLOWED) {
615 #ifdef CESA_OCF_SPLIT
616 /* if both encrypt and auth try to split */
617 if(auth && (encrypt || decrypt)) {
618 MV_CESA_COMMAND *cesa_cmd_wa;
619
620 /* malloc a new cesa process and init it */
621 cesa_ocf_cmd_wa = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
622
623 if (cesa_ocf_cmd_wa == NULL) {
624 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
625 goto p_error;
626 }
627 memcpy(cesa_ocf_cmd_wa, cesa_ocf_cmd, sizeof(struct cesa_ocf_process));
628 cesa_cmd_wa = &cesa_ocf_cmd_wa->cesa_cmd;
629 cesa_cmd_wa->pReqPrv = (void *)cesa_ocf_cmd_wa;
630 cesa_ocf_cmd_wa->need_cb = 0;
631
632 /* break requests to two operation, first operation completion won't call callback */
633 if((decrypt) && (cesa_ocf_cur_ses->auth_tn_decrypt)) {
634 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
635 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
636 }
637 else if((decrypt) && !(cesa_ocf_cur_ses->auth_tn_decrypt)) {
638 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_decrypt;
639 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
640 }
641 else if((encrypt) && (cesa_ocf_cur_ses->encrypt_tn_auth)) {
642 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
643 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
644 }
645 else if((encrypt) && !(cesa_ocf_cur_ses->encrypt_tn_auth)){
646 cesa_cmd_wa->sessionId = cesa_ocf_cur_ses->frag_wa_auth;
647 cesa_cmd->sessionId = cesa_ocf_cur_ses->frag_wa_encrypt;
648 }
649 else {
650 printk("%s,%d: Unsupporterd fragment wa mode \n", __FILE__, __LINE__);
651 goto p_error;
652 }
653
654 /* send the 2 actions to the HAL */
655 spin_lock_irqsave(&cesa_lock, flags);
656 status = mvCesaAction(cesa_cmd_wa);
657 spin_unlock_irqrestore(&cesa_lock, flags);
658
659 if((status != MV_NO_MORE) && (status != MV_OK)) {
660 printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
661 goto p_error;
662 }
663 spin_lock_irqsave(&cesa_lock, flags);
664 status = mvCesaAction(cesa_cmd);
665 spin_unlock_irqrestore(&cesa_lock, flags);
666
667 }
668 /* action not allowed and can't split */
669 else
670 #endif
671 {
672 goto p_error;
673 }
674 }
675
676 /* Hal Q is full, send again. This should never happen */
677 if(status == MV_NO_RESOURCE) {
678 printk("%s,%d: cesa no more resources \n", __FILE__, __LINE__);
679 if(cesa_ocf_cmd)
680 kfree(cesa_ocf_cmd);
681 if(cesa_ocf_cmd_wa)
682 kfree(cesa_ocf_cmd_wa);
683 return ERESTART;
684 }
685 else if((status != MV_NO_MORE) && (status != MV_OK)) {
686 printk("%s,%d: cesa action failed, status = 0x%x\n", __FILE__, __LINE__, status);
687 goto p_error;
688 }
689
690
691 #ifdef CESA_OCF_POLLING
692 cesa_interrupt_polling();
693 #endif
694 cesaTestTraceAdd(5);
695
696 return 0;
697 p_error:
698 crp->crp_etype = EINVAL;
699 if(cesa_ocf_cmd)
700 kfree(cesa_ocf_cmd);
701 if(cesa_ocf_cmd_wa)
702 kfree(cesa_ocf_cmd_wa);
703 return EINVAL;
704 }
705
706 /*
707 * cesa callback.
708 */
709 static void
710 cesa_callback(unsigned long dummy)
711 {
712 struct cesa_ocf_process *cesa_ocf_cmd = NULL;
713 struct cryptop *crp = NULL;
714 MV_CESA_RESULT result[MV_CESA_MAX_CHAN];
715 int res_idx = 0,i;
716 MV_STATUS status;
717
718 dprintk("%s()\n", __FUNCTION__);
719
720 #ifdef CESA_OCF_TASKLET
721 disable_irq(cesa_device.irq);
722 #endif
723 while(MV_TRUE) {
724
725 /* Get Ready requests */
726 spin_lock(&cesa_lock);
727 status = mvCesaReadyGet(&result[res_idx]);
728 spin_unlock(&cesa_lock);
729
730 cesaTestTraceAdd(2);
731
732 if(status != MV_OK) {
733 #ifdef CESA_OCF_POLLING
734 if(status == MV_BUSY) { /* Fragment */
735 cesa_interrupt_polling();
736 return;
737 }
738 #endif
739 break;
740 }
741 res_idx++;
742 break;
743 }
744
745 for(i = 0; i < res_idx; i++) {
746
747 if(!result[i].pReqPrv) {
748 printk("%s,%d: warning private is NULL\n", __FILE__, __LINE__);
749 break;
750 }
751
752 cesa_ocf_cmd = result[i].pReqPrv;
753 crp = cesa_ocf_cmd->crp;
754
755 // ignore HMAC error.
756 //if(result->retCode)
757 // crp->crp_etype = EIO;
758
759 #if defined(CESA_OCF_POLLING)
760 if(!cesa_ocf_cmd->need_cb){
761 cesa_interrupt_polling();
762 }
763 #endif
764 if(cesa_ocf_cmd->need_cb) {
765 if(debug) {
766 mvCesaDebugMbuf("DST BUFFER", cesa_ocf_cmd->cesa_cmd.pDst, 0, cesa_ocf_cmd->cesa_cmd.pDst->mbufSize);
767 }
768 crypto_done(crp);
769 }
770 kfree(cesa_ocf_cmd);
771 }
772 #ifdef CESA_OCF_TASKLET
773 enable_irq(cesa_device.irq);
774 #endif
775
776 cesaTestTraceAdd(3);
777
778 return;
779 }
780
781 #ifdef CESA_OCF_POLLING
782 static void
783 cesa_interrupt_polling(void)
784 {
785 u32 cause;
786
787 dprintk("%s()\n", __FUNCTION__);
788
789 /* Read cause register */
790 do {
791 cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
792 cause &= MV_CESA_CAUSE_ACC_DMA_ALL_MASK;
793
794 } while (cause == 0);
795
796 /* clear interrupts */
797 MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
798
799 cesa_callback(0);
800
801 return;
802 }
803
804 #endif
805
806 /*
807 * cesa Interrupt polling routine.
808 */
809 static irqreturn_t
810 cesa_interrupt_handler(int irq, void *arg)
811 {
812 u32 cause;
813
814 dprintk("%s()\n", __FUNCTION__);
815
816 cesaTestTraceAdd(0);
817
818 /* Read cause register */
819 cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
820
821 if( (cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) == 0)
822 {
823 /* Empty interrupt */
824 dprintk("%s,%d: cesaTestReadyIsr: cause=0x%x\n", __FILE__, __LINE__, cause);
825 return IRQ_HANDLED;
826 }
827
828 /* clear interrupts */
829 MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
830
831 cesaTestTraceAdd(1);
832 #ifdef CESA_OCF_TASKLET
833 tasklet_hi_schedule(&cesa_ocf_tasklet);
834 #else
835 cesa_callback(0);
836 #endif
837 return IRQ_HANDLED;
838 }
839
840 /*
841 * Open a session.
842 */
843 static int
844 /*cesa_ocf_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)*/
845 cesa_ocf_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
846 {
847 u32 status = 0, i;
848 u32 count = 0, auth = 0, encrypt =0;
849 struct cesa_ocf_data *cesa_ocf_cur_ses;
850 MV_CESA_OPEN_SESSION cesa_session;
851 MV_CESA_OPEN_SESSION *cesa_ses = &cesa_session;
852
853
854 dprintk("%s()\n", __FUNCTION__);
855 if (sid == NULL || cri == NULL) {
856 printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
857 return EINVAL;
858 }
859
860 /* leave first empty like in other implementations */
861 for (i = 1; i < CESA_OCF_MAX_SES; i++) {
862 if (cesa_ocf_sessions[i] == NULL)
863 break;
864 }
865
866 if(i >= CESA_OCF_MAX_SES) {
867 printk("%s,%d: no more sessions \n", __FILE__, __LINE__);
868 return EINVAL;
869 }
870
871 cesa_ocf_sessions[i] = (struct cesa_ocf_data *) kmalloc(sizeof(struct cesa_ocf_data), GFP_ATOMIC);
872 if (cesa_ocf_sessions[i] == NULL) {
873 cesa_ocf_freesession(NULL, i);
874 printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
875 return ENOBUFS;
876 }
877 dprintk("%s,%d: new session %d \n", __FILE__, __LINE__, i);
878
879 *sid = i;
880 cesa_ocf_cur_ses = cesa_ocf_sessions[i];
881 memset(cesa_ocf_cur_ses, 0, sizeof(struct cesa_ocf_data));
882 cesa_ocf_cur_ses->sid_encrypt = -1;
883 cesa_ocf_cur_ses->sid_decrypt = -1;
884 cesa_ocf_cur_ses->frag_wa_encrypt = -1;
885 cesa_ocf_cur_ses->frag_wa_decrypt = -1;
886 cesa_ocf_cur_ses->frag_wa_auth = -1;
887
888 /* init the session */
889 memset(cesa_ses, 0, sizeof(MV_CESA_OPEN_SESSION));
890 count = 1;
891 while (cri) {
892 if(count > 2) {
893 printk("%s,%d: don't support more then 2 operations\n", __FILE__, __LINE__);
894 goto error;
895 }
896 switch (cri->cri_alg) {
897 case CRYPTO_AES_CBC:
898 dprintk("%s,%d: (%d) AES CBC \n", __FILE__, __LINE__, count);
899 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
900 cesa_ocf_cur_ses->ivlen = MV_CESA_AES_BLOCK_SIZE;
901 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_AES;
902 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
903 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
904 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
905 goto error;
906 }
907 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
908 dprintk("%s,%d: key length %d \n", __FILE__, __LINE__, cri->cri_klen/8);
909 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
910 encrypt += count;
911 break;
912 case CRYPTO_3DES_CBC:
913 dprintk("%s,%d: (%d) 3DES CBC \n", __FILE__, __LINE__, count);
914 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
915 cesa_ocf_cur_ses->ivlen = MV_CESA_3DES_BLOCK_SIZE;
916 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_3DES;
917 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
918 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
919 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
920 goto error;
921 }
922 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
923 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
924 encrypt += count;
925 break;
926 case CRYPTO_DES_CBC:
927 dprintk("%s,%d: (%d) DES CBC \n", __FILE__, __LINE__, count);
928 cesa_ocf_cur_ses->cipher_alg = cri->cri_alg;
929 cesa_ocf_cur_ses->ivlen = MV_CESA_DES_BLOCK_SIZE;
930 cesa_ses->cryptoAlgorithm = MV_CESA_CRYPTO_DES;
931 cesa_ses->cryptoMode = MV_CESA_CRYPTO_CBC;
932 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
933 printk("%s,%d: CRYPTO key too long.\n", __FILE__, __LINE__);
934 goto error;
935 }
936 memcpy(cesa_ses->cryptoKey, cri->cri_key, cri->cri_klen/8);
937 cesa_ses->cryptoKeyLength = cri->cri_klen/8;
938 encrypt += count;
939 break;
940 case CRYPTO_MD5:
941 case CRYPTO_MD5_HMAC:
942 dprintk("%s,%d: (%d) %sMD5 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_MD5)? "H-":" ");
943 cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
944 cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MD5_DIGEST_SIZE : 12;
945 cesa_ses->macMode = (cri->cri_alg == CRYPTO_MD5)? MV_CESA_MAC_MD5 : MV_CESA_MAC_HMAC_MD5;
946 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
947 printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
948 goto error;
949 }
950 cesa_ses->macKeyLength = cri->cri_klen/8;
951 memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
952 cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen;
953 auth += count;
954 break;
955 case CRYPTO_SHA1:
956 case CRYPTO_SHA1_HMAC:
957 dprintk("%s,%d: (%d) %sSHA1 CBC \n", __FILE__, __LINE__, count, (cri->cri_alg != CRYPTO_SHA1)? "H-":" ");
958 cesa_ocf_cur_ses->auth_alg = cri->cri_alg;
959 cesa_ocf_cur_ses->digestlen = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_SHA1_DIGEST_SIZE : 12;
960 cesa_ses->macMode = (cri->cri_alg == CRYPTO_SHA1)? MV_CESA_MAC_SHA1 : MV_CESA_MAC_HMAC_SHA1;
961 if(cri->cri_klen/8 > MV_CESA_MAX_CRYPTO_KEY_LENGTH) {
962 printk("%s,%d: MAC key too long. \n", __FILE__, __LINE__);
963 goto error;
964 }
965 cesa_ses->macKeyLength = cri->cri_klen/8;
966 memcpy(cesa_ses->macKey, cri->cri_key, cri->cri_klen/8);
967 cesa_ses->digestSize = cesa_ocf_cur_ses->digestlen;
968 auth += count;
969 break;
970 default:
971 printk("%s,%d: unknown algo 0x%x\n", __FILE__, __LINE__, cri->cri_alg);
972 goto error;
973 }
974 cri = cri->cri_next;
975 count++;
976 }
977
978 if((encrypt > 2) || (auth > 2)) {
979 printk("%s,%d: session mode is not supported.\n", __FILE__, __LINE__);
980 goto error;
981 }
982 /* create new sessions in HAL */
983 if(encrypt) {
984 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
985 /* encrypt session */
986 if(auth == 1) {
987 cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
988 }
989 else if(auth == 2) {
990 cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
991 cesa_ocf_cur_ses->encrypt_tn_auth = 1;
992 }
993 else {
994 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
995 }
996 cesa_ses->direction = MV_CESA_DIR_ENCODE;
997 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
998 if(status != MV_OK) {
999 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1000 goto error;
1001 }
1002 /* decrypt session */
1003 if( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) {
1004 cesa_ses->operation = MV_CESA_CRYPTO_THEN_MAC;
1005 }
1006 else if( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC ) {
1007 cesa_ses->operation = MV_CESA_MAC_THEN_CRYPTO;
1008 }
1009 cesa_ses->direction = MV_CESA_DIR_DECODE;
1010 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_decrypt);
1011 if(status != MV_OK) {
1012 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1013 goto error;
1014 }
1015
1016 /* preapre one action sessions for case we will need to split an action */
1017 #ifdef CESA_OCF_SPLIT
1018 if(( cesa_ses->operation == MV_CESA_MAC_THEN_CRYPTO ) ||
1019 ( cesa_ses->operation == MV_CESA_CRYPTO_THEN_MAC )) {
1020 /* open one session for encode and one for decode */
1021 cesa_ses->operation = MV_CESA_CRYPTO_ONLY;
1022 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1023 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_encrypt);
1024 if(status != MV_OK) {
1025 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1026 goto error;
1027 }
1028
1029 cesa_ses->direction = MV_CESA_DIR_DECODE;
1030 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_decrypt);
1031 if(status != MV_OK) {
1032 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1033 goto error;
1034 }
1035 /* open one session for auth */
1036 cesa_ses->operation = MV_CESA_MAC_ONLY;
1037 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1038 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_auth);
1039 if(status != MV_OK) {
1040 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1041 goto error;
1042 }
1043 }
1044 #endif
1045 }
1046 else { /* only auth */
1047 cesa_ses->operation = MV_CESA_MAC_ONLY;
1048 cesa_ses->direction = MV_CESA_DIR_ENCODE;
1049 status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
1050 if(status != MV_OK) {
1051 printk("%s,%d: Can't open new session - status = 0x%x\n", __FILE__, __LINE__, status);
1052 goto error;
1053 }
1054 }
1055
1056 return 0;
1057 error:
1058 cesa_ocf_freesession(NULL, *sid);
1059 return EINVAL;
1060
1061 }
1062
1063
1064 /*
1065 * Free a session.
1066 */
1067 static int
1068 cesa_ocf_freesession(device_t dev, u_int64_t tid)
1069 {
1070 struct cesa_ocf_data *cesa_ocf_cur_ses;
1071 u_int32_t sid = CRYPTO_SESID2LID(tid);
1072 //unsigned long flags;
1073
1074 dprintk("%s() %d \n", __FUNCTION__, sid);
1075 if ( (sid >= CESA_OCF_MAX_SES) || (cesa_ocf_sessions[sid] == NULL) ) {
1076 printk("%s,%d: EINVAL can't free session %d \n", __FILE__, __LINE__, sid);
1077 return(EINVAL);
1078 }
1079
1080 /* Silently accept and return */
1081 if (sid == 0)
1082 return(0);
1083
1084 /* release session from HAL */
1085 cesa_ocf_cur_ses = cesa_ocf_sessions[sid];
1086 if (cesa_ocf_cur_ses->sid_encrypt != -1) {
1087 mvCesaSessionClose(cesa_ocf_cur_ses->sid_encrypt);
1088 }
1089 if (cesa_ocf_cur_ses->sid_decrypt != -1) {
1090 mvCesaSessionClose(cesa_ocf_cur_ses->sid_decrypt);
1091 }
1092 if (cesa_ocf_cur_ses->frag_wa_encrypt != -1) {
1093 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_encrypt);
1094 }
1095 if (cesa_ocf_cur_ses->frag_wa_decrypt != -1) {
1096 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_decrypt);
1097 }
1098 if (cesa_ocf_cur_ses->frag_wa_auth != -1) {
1099 mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_auth);
1100 }
1101
1102 kfree(cesa_ocf_cur_ses);
1103 cesa_ocf_sessions[sid] = NULL;
1104
1105 return 0;
1106 }
1107
1108
1109 /* TDMA Window setup */
1110
1111 static void __init
1112 setup_tdma_mbus_windows(struct cesa_dev *dev)
1113 {
1114 int i;
1115
1116 for (i = 0; i < 4; i++) {
1117 writel(0, dev->reg + WINDOW_BASE(i));
1118 writel(0, dev->reg + WINDOW_CTRL(i));
1119 }
1120
1121 for (i = 0; i < dev->plat_data->dram->num_cs; i++) {
1122 struct mbus_dram_window *cs = dev->plat_data->dram->cs + i;
1123 writel(
1124 ((cs->size - 1) & 0xffff0000) |
1125 (cs->mbus_attr << 8) |
1126 (dev->plat_data->dram->mbus_dram_target_id << 4) | 1,
1127 dev->reg + WINDOW_CTRL(i)
1128 );
1129 writel(cs->base, dev->reg + WINDOW_BASE(i));
1130 }
1131 }
1132
1133 /*
1134 * our driver startup and shutdown routines
1135 */
1136 static int
1137 mv_cesa_ocf_init(struct platform_device *pdev)
1138 {
1139 #if defined(CONFIG_MV78200) || defined(CONFIG_MV632X)
1140 if (MV_FALSE == mvSocUnitIsMappedToThisCpu(CESA))
1141 {
1142 dprintk("CESA is not mapped to this CPU\n");
1143 return -ENODEV;
1144 }
1145 #endif
1146
1147 dprintk("%s\n", __FUNCTION__);
1148 memset(&mv_cesa_dev, 0, sizeof(mv_cesa_dev));
1149 softc_device_init(&mv_cesa_dev, "MV CESA", 0, mv_cesa_methods);
1150 cesa_ocf_id = crypto_get_driverid(softc_get_device(&mv_cesa_dev),CRYPTOCAP_F_HARDWARE);
1151
1152 if (cesa_ocf_id < 0)
1153 panic("MV CESA crypto device cannot initialize!");
1154
1155 dprintk("%s,%d: cesa ocf device id is %d \n", __FILE__, __LINE__, cesa_ocf_id);
1156
1157 /* CESA unit is auto power on off */
1158 #if 0
1159 if (MV_FALSE == mvCtrlPwrClckGet(CESA_UNIT_ID,0))
1160 {
1161 printk("\nWarning CESA %d is Powered Off\n",0);
1162 return EINVAL;
1163 }
1164 #endif
1165
1166 memset(&cesa_device, 0, sizeof(struct cesa_dev));
1167 /* Get the IRQ, and crypto memory regions */
1168 {
1169 struct resource *res;
1170 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
1171
1172 if (!res)
1173 return -ENXIO;
1174
1175 cesa_device.sram = ioremap(res->start, res->end - res->start + 1);
1176 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
1177
1178 if (!res) {
1179 iounmap(cesa_device.sram);
1180 return -ENXIO;
1181 }
1182 cesa_device.reg = ioremap(res->start, res->end - res->start + 1);
1183 cesa_device.irq = platform_get_irq(pdev, 0);
1184 cesa_device.plat_data = pdev->dev.platform_data;
1185 setup_tdma_mbus_windows(&cesa_device);
1186
1187 }
1188
1189
1190 if( MV_OK != mvCesaInit(CESA_OCF_MAX_SES*5, CESA_Q_SIZE, cesa_device.reg,
1191 NULL) ) {
1192 printk("%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
1193 return EINVAL;
1194 }
1195
1196 /* clear and unmask Int */
1197 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
1198 #ifndef CESA_OCF_POLLING
1199 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, MV_CESA_CAUSE_ACC_DMA_MASK);
1200 #endif
1201 #ifdef CESA_OCF_TASKLET
1202 tasklet_init(&cesa_ocf_tasklet, cesa_callback, (unsigned int) 0);
1203 #endif
1204 /* register interrupt */
1205 if( request_irq( cesa_device.irq, cesa_interrupt_handler,
1206 (IRQF_DISABLED) , "cesa", &cesa_ocf_id) < 0) {
1207 printk("%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, cesa_device.reg);
1208 return EINVAL;
1209 }
1210
1211
1212 memset(cesa_ocf_sessions, 0, sizeof(struct cesa_ocf_data *) * CESA_OCF_MAX_SES);
1213
1214 #define REGISTER(alg) \
1215 crypto_register(cesa_ocf_id, alg, 0,0)
1216 REGISTER(CRYPTO_AES_CBC);
1217 REGISTER(CRYPTO_DES_CBC);
1218 REGISTER(CRYPTO_3DES_CBC);
1219 REGISTER(CRYPTO_MD5);
1220 REGISTER(CRYPTO_MD5_HMAC);
1221 REGISTER(CRYPTO_SHA1);
1222 REGISTER(CRYPTO_SHA1_HMAC);
1223 #undef REGISTER
1224
1225 return 0;
1226 }
1227
1228 static void
1229 mv_cesa_ocf_exit(struct platform_device *pdev)
1230 {
1231 dprintk("%s()\n", __FUNCTION__);
1232
1233 crypto_unregister_all(cesa_ocf_id);
1234 cesa_ocf_id = -1;
1235 iounmap(cesa_device.reg);
1236 iounmap(cesa_device.sram);
1237 free_irq(cesa_device.irq, NULL);
1238
1239 /* mask and clear Int */
1240 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
1241 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
1242
1243
1244 if( MV_OK != mvCesaFinish() ) {
1245 printk("%s,%d: mvCesaFinish Failed. \n", __FILE__, __LINE__);
1246 return;
1247 }
1248 }
1249
1250
1251 void cesa_ocf_debug(void)
1252 {
1253
1254 #ifdef CESA_OCF_TRACE_DEBUG
1255 {
1256 int i, j;
1257 j = cesaTestTraceIdx;
1258 mvOsPrintf("No Type rCause iCause Proc Isr Res Time pReady pProc pEmpty\n");
1259 for(i=0; i<MV_CESA_TEST_TRACE_SIZE; i++)
1260 {
1261 mvOsPrintf("%02d. %d 0x%04x 0x%04x 0x%02x 0x%02x %02d 0x%06x %p %p %p\n",
1262 j, cesaTestTrace[j].type, cesaTestTrace[j].realCause,
1263 cesaTestTrace[j].idmaCause,
1264 cesaTestTrace[j].resources, cesaTestTrace[j].timeStamp,
1265 cesaTestTrace[j].pReqReady, cesaTestTrace[j].pReqProcess, cesaTestTrace[j].pReqEmpty);
1266 j++;
1267 if(j == MV_CESA_TEST_TRACE_SIZE)
1268 j = 0;
1269 }
1270 }
1271 #endif
1272
1273 }
1274
1275 static struct platform_driver marvell_cesa = {
1276 .probe = mv_cesa_ocf_init,
1277 .remove = mv_cesa_ocf_exit,
1278 .driver = {
1279 .owner = THIS_MODULE,
1280 .name = "mv_crypto",
1281 },
1282 };
1283
1284 MODULE_ALIAS("platform:mv_crypto");
1285
1286 static int __init mv_cesa_init(void)
1287 {
1288 return platform_driver_register(&marvell_cesa);
1289 }
1290
1291 module_init(mv_cesa_init);
1292
1293 static void __exit mv_cesa_exit(void)
1294 {
1295 platform_driver_unregister(&marvell_cesa);
1296 }
1297
1298 module_exit(mv_cesa_exit);
1299
1300 MODULE_LICENSE("GPL");
1301 MODULE_AUTHOR("Ronen Shitrit");
1302 MODULE_DESCRIPTION("OCF module for Orion CESA crypto");