ocf: update to version 20120127
[15.05/openwrt.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");