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

Archive Download this file



interactive