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