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