Root/target/linux/generic/files/crypto/ocf/kirkwood/cesa_ocf_drv.c

1/*******************************************************************************
2Copyright (C) Marvell International Ltd. and its affiliates
3
4This software file (the "File") is owned and distributed by Marvell
5International Ltd. and/or its affiliates ("Marvell") under the following
6alternative licensing terms. Once you have made an election to distribute the
7File under one of the following license alternatives, please (i) delete this
8introductory statement regarding license alternatives, (ii) delete the two
9license alternatives that you have not elected to use and (iii) preserve the
10Marvell copyright notice above.
11
12
13********************************************************************************
14Marvell GPL License Option
15
16If you received this File from Marvell, you may opt to use, redistribute and/or
17modify this File in accordance with the terms and conditions of the General
18Public License Version 2, June 1991 (the "GPL License"), a copy of which is
19available along with the File in the license.txt file or by writing to the Free
20Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
21on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
22
23THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
24WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
25DISCLAIMED. The GPL License provides additional details about this warranty
26disclaimer.
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
65static int debug = 1;
66module_param(debug, int, 1);
67MODULE_PARM_DESC(debug, "Enable debug");
68#undef dprintk
69#define dprintk(a...) if (debug) { printk(a); } else
70#else
71static 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
89extern 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 */
99struct 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 */
115struct 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
123struct 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 */
134static int32_t cesa_ocf_id = -1;
135static struct cesa_ocf_data *cesa_ocf_sessions[CESA_OCF_MAX_SES];
136static spinlock_t cesa_lock;
137static struct cesa_dev cesa_device;
138
139/* static APIs */
140static int cesa_ocf_process (device_t, struct cryptop *, int);
141static int cesa_ocf_newsession (device_t, u_int32_t *, struct cryptoini *);
142static int cesa_ocf_freesession (device_t, u_int64_t);
143static void cesa_callback (unsigned long);
144static irqreturn_t cesa_interrupt_handler (int, void *);
145#ifdef CESA_OCF_POLLING
146static void cesa_interrupt_polling(void);
147#endif
148#ifdef CESA_OCF_TASKLET
149static struct tasklet_struct cesa_ocf_tasklet;
150#endif
151
152static struct timeval tt_start;
153static struct timeval tt_end;
154
155/*
156 * dummy device structure
157 */
158
159static struct {
160    softc_device_decl sc_dev;
161} mv_cesa_dev;
162
163static 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
179typedef 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
194static int cesaTestTraceIdx = 0;
195static MV_CESA_TEST_TRACE cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
196
197static 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
218unsigned int
219get_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 */
242static int
243ocf_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 */
309static int
310cesa_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;
694p_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 */
706static void
707cesa_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
779static void
780cesa_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 */
806static irqreturn_t
807cesa_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 */
840static int
841/*cesa_ocf_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)*/
842cesa_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;
1054error:
1055         cesa_ocf_freesession(NULL, *sid);
1056          return EINVAL;
1057
1058}
1059
1060
1061/*
1062 * Free a session.
1063 */
1064static int
1065cesa_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
1108static void __init
1109setup_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 */
1133static int
1134mv_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
1225static void
1226mv_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
1248void 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
1272static 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
1281MODULE_ALIAS("platform:mv_crypto");
1282
1283static int __init mv_cesa_init(void)
1284{
1285    return platform_driver_register(&marvell_cesa);
1286}
1287
1288module_init(mv_cesa_init);
1289
1290static void __exit mv_cesa_exit(void)
1291{
1292    platform_driver_unregister(&marvell_cesa);
1293}
1294
1295module_exit(mv_cesa_exit);
1296
1297MODULE_LICENSE("GPL");
1298MODULE_AUTHOR("Ronen Shitrit");
1299MODULE_DESCRIPTION("OCF module for Orion CESA crypto");
1300

Archive Download this file



interactive