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

Archive Download this file



interactive