2 * Copyright (C) 2007 PA Semi, Inc
4 * Driver for the PA Semi PWRficient DMA Crypto Engine
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #ifndef AUTOCONF_INCLUDED
21 #include <linux/config.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/interrupt.h>
26 #include <linux/timer.h>
27 #include <linux/random.h>
28 #include <linux/skbuff.h>
29 #include <asm/scatterlist.h>
30 #include <linux/moduleparam.h>
31 #include <linux/pci.h>
32 #include <cryptodev.h>
34 #include "pasemi_fnu.h"
36 #define DRV_NAME "pasemi"
38 #define TIMER_INTERVAL 1000
40 static void __devexit
pasemi_dma_remove(struct pci_dev
*pdev
);
41 static struct pasdma_status
volatile * dma_status
;
44 module_param(debug
, int, 0644);
45 MODULE_PARM_DESC(debug
, "Enable debug");
47 static void pasemi_desc_start(struct pasemi_desc
*desc
, u64 hdr
)
55 static void pasemi_desc_build(struct pasemi_desc
*desc
, u64 val
)
57 desc
->quad
[desc
->quad_cnt
++] = val
;
58 desc
->size
= (desc
->quad_cnt
+ 1) / 2;
61 static void pasemi_desc_hdr(struct pasemi_desc
*desc
, u64 hdr
)
66 static int pasemi_desc_size(struct pasemi_desc
*desc
)
71 static void pasemi_ring_add_desc(
72 struct pasemi_fnu_txring
*ring
,
73 struct pasemi_desc
*desc
,
74 struct cryptop
*crp
) {
76 int ring_index
= 2 * (ring
->next_to_fill
& (TX_RING_SIZE
-1));
78 TX_DESC_INFO(ring
, ring
->next_to_fill
).desc_size
= desc
->size
;
79 TX_DESC_INFO(ring
, ring
->next_to_fill
).desc_postop
= desc
->postop
;
80 TX_DESC_INFO(ring
, ring
->next_to_fill
).cf_crp
= crp
;
82 for (i
= 0; i
< desc
->quad_cnt
; i
+= 2) {
83 ring_index
= 2 * (ring
->next_to_fill
& (TX_RING_SIZE
-1));
84 ring
->desc
[ring_index
] = desc
->quad
[i
];
85 ring
->desc
[ring_index
+ 1] = desc
->quad
[i
+ 1];
89 if (desc
->quad_cnt
& 1)
90 ring
->desc
[ring_index
+ 1] = 0;
93 static void pasemi_ring_incr(struct pasemi_softc
*sc
, int chan_index
, int incr
)
95 out_le32(sc
->dma_regs
+ PAS_DMA_TXCHAN_INCR(sc
->base_chan
+ chan_index
),
100 * Generate a new software session.
103 pasemi_newsession(device_t dev
, u_int32_t
*sidp
, struct cryptoini
*cri
)
105 struct cryptoini
*c
, *encini
= NULL
, *macini
= NULL
;
106 struct pasemi_softc
*sc
= device_get_softc(dev
);
107 struct pasemi_session
*ses
= NULL
, **sespp
;
111 struct pasemi_desc init_desc
;
112 struct pasemi_fnu_txring
*txring
;
114 DPRINTF("%s()\n", __FUNCTION__
);
115 if (sidp
== NULL
|| cri
== NULL
|| sc
== NULL
) {
116 DPRINTF("%s,%d - EINVAL\n", __FILE__
, __LINE__
);
119 for (c
= cri
; c
!= NULL
; c
= c
->cri_next
) {
120 if (ALG_IS_SIG(c
->cri_alg
)) {
124 } else if (ALG_IS_CIPHER(c
->cri_alg
)) {
129 DPRINTF("UNKNOWN c->cri_alg %d\n", c
->cri_alg
);
133 if (encini
== NULL
&& macini
== NULL
)
136 /* validate key length */
137 switch (encini
->cri_alg
) {
139 if (encini
->cri_klen
!= 64)
141 ccmd
= DMA_CALGO_DES
;
143 case CRYPTO_3DES_CBC
:
144 if (encini
->cri_klen
!= 192)
146 ccmd
= DMA_CALGO_3DES
;
149 if (encini
->cri_klen
!= 128 &&
150 encini
->cri_klen
!= 192 &&
151 encini
->cri_klen
!= 256)
153 ccmd
= DMA_CALGO_AES
;
156 if (encini
->cri_klen
!= 128)
158 ccmd
= DMA_CALGO_ARC
;
161 DPRINTF("UNKNOWN encini->cri_alg %d\n",
168 switch (macini
->cri_alg
) {
170 case CRYPTO_MD5_HMAC
:
174 case CRYPTO_SHA1_HMAC
:
178 DPRINTF("UNKNOWN macini->cri_alg %d\n",
182 if (((macini
->cri_klen
+ 7) / 8) > blksz
) {
183 DPRINTF("key length %d bigger than blksize %d not supported\n",
184 ((macini
->cri_klen
+ 7) / 8), blksz
);
189 for (sesn
= 0; sesn
< sc
->sc_nsessions
; sesn
++) {
190 if (sc
->sc_sessions
[sesn
] == NULL
) {
191 sc
->sc_sessions
[sesn
] = (struct pasemi_session
*)
192 kzalloc(sizeof(struct pasemi_session
), GFP_ATOMIC
);
193 ses
= sc
->sc_sessions
[sesn
];
195 } else if (sc
->sc_sessions
[sesn
]->used
== 0) {
196 ses
= sc
->sc_sessions
[sesn
];
202 sespp
= (struct pasemi_session
**)
203 kzalloc(sc
->sc_nsessions
* 2 *
204 sizeof(struct pasemi_session
*), GFP_ATOMIC
);
207 memcpy(sespp
, sc
->sc_sessions
,
208 sc
->sc_nsessions
* sizeof(struct pasemi_session
*));
209 kfree(sc
->sc_sessions
);
210 sc
->sc_sessions
= sespp
;
211 sesn
= sc
->sc_nsessions
;
212 ses
= sc
->sc_sessions
[sesn
] = (struct pasemi_session
*)
213 kzalloc(sizeof(struct pasemi_session
), GFP_ATOMIC
);
216 sc
->sc_nsessions
*= 2;
221 ses
->dma_addr
= pci_map_single(sc
->dma_pdev
, (void *) ses
->civ
,
222 sizeof(struct pasemi_session
), DMA_TO_DEVICE
);
224 /* enter the channel scheduler */
225 spin_lock_irqsave(&sc
->sc_chnlock
, flags
);
227 /* ARC4 has to be processed by the even channel */
228 if (encini
&& (encini
->cri_alg
== CRYPTO_ARC4
))
229 ses
->chan
= sc
->sc_lastchn
& ~1;
231 ses
->chan
= sc
->sc_lastchn
;
232 sc
->sc_lastchn
= (sc
->sc_lastchn
+ 1) % sc
->sc_num_channels
;
234 spin_unlock_irqrestore(&sc
->sc_chnlock
, flags
);
236 txring
= &sc
->tx
[ses
->chan
];
242 /* XXX may read fewer than requested */
243 get_random_bytes(ses
->civ
, sizeof(ses
->civ
));
245 ses
->keysz
= (encini
->cri_klen
- 63) / 64;
246 memcpy(ses
->key
, encini
->cri_key
, (ses
->keysz
+ 1) * 8);
248 pasemi_desc_start(&init_desc
,
249 XCT_CTRL_HDR(ses
->chan
, (encini
&& macini
) ? 0x68 : 0x40, DMA_FN_CIV0
));
250 pasemi_desc_build(&init_desc
,
251 XCT_FUN_SRC_PTR((encini
&& macini
) ? 0x68 : 0x40, ses
->dma_addr
));
254 if (macini
->cri_alg
== CRYPTO_MD5_HMAC
||
255 macini
->cri_alg
== CRYPTO_SHA1_HMAC
)
256 memcpy(ses
->hkey
, macini
->cri_key
, blksz
);
258 /* Load initialization constants(RFC 1321, 3174) */
259 ses
->hiv
[0] = 0x67452301efcdab89ULL
;
260 ses
->hiv
[1] = 0x98badcfe10325476ULL
;
261 ses
->hiv
[2] = 0xc3d2e1f000000000ULL
;
266 spin_lock_irqsave(&txring
->fill_lock
, flags
);
268 if (((txring
->next_to_fill
+ pasemi_desc_size(&init_desc
)) -
269 txring
->next_to_clean
) > TX_RING_SIZE
) {
270 spin_unlock_irqrestore(&txring
->fill_lock
, flags
);
275 pasemi_ring_add_desc(txring
, &init_desc
, NULL
);
276 pasemi_ring_incr(sc
, ses
->chan
,
277 pasemi_desc_size(&init_desc
));
281 spin_unlock_irqrestore(&txring
->fill_lock
, flags
);
283 *sidp
= PASEMI_SID(sesn
);
288 * Deallocate a session.
291 pasemi_freesession(device_t dev
, u_int64_t tid
)
293 struct pasemi_softc
*sc
= device_get_softc(dev
);
295 u_int32_t sid
= ((u_int32_t
) tid
) & 0xffffffff;
297 DPRINTF("%s()\n", __FUNCTION__
);
301 session
= PASEMI_SESSION(sid
);
302 if (session
>= sc
->sc_nsessions
|| !sc
->sc_sessions
[session
])
305 pci_unmap_single(sc
->dma_pdev
,
306 sc
->sc_sessions
[session
]->dma_addr
,
307 sizeof(struct pasemi_session
), DMA_TO_DEVICE
);
308 memset(sc
->sc_sessions
[session
], 0,
309 sizeof(struct pasemi_session
));
315 pasemi_process(device_t dev
, struct cryptop
*crp
, int hint
)
318 int err
= 0, ivsize
, srclen
= 0, reinit
= 0, reinit_size
= 0, chsel
;
319 struct pasemi_softc
*sc
= device_get_softc(dev
);
320 struct cryptodesc
*crd1
, *crd2
, *maccrd
, *enccrd
;
322 struct pasemi_desc init_desc
, work_desc
;
323 struct pasemi_session
*ses
;
327 struct pasemi_fnu_txring
*txring
;
329 DPRINTF("%s()\n", __FUNCTION__
);
331 if (crp
== NULL
|| crp
->crp_callback
== NULL
|| sc
== NULL
)
335 if (PASEMI_SESSION(crp
->crp_sid
) >= sc
->sc_nsessions
)
338 ses
= sc
->sc_sessions
[PASEMI_SESSION(crp
->crp_sid
)];
340 crd1
= crp
->crp_desc
;
345 crd2
= crd1
->crd_next
;
347 if (ALG_IS_SIG(crd1
->crd_alg
)) {
351 else if (ALG_IS_CIPHER(crd2
->crd_alg
) &&
352 (crd2
->crd_flags
& CRD_F_ENCRYPT
) == 0)
356 } else if (ALG_IS_CIPHER(crd1
->crd_alg
)) {
360 else if (ALG_IS_SIG(crd2
->crd_alg
) &&
361 (crd1
->crd_flags
& CRD_F_ENCRYPT
))
370 txring
= &sc
->tx
[chsel
];
372 if (enccrd
&& !maccrd
) {
373 if (enccrd
->crd_alg
== CRYPTO_ARC4
)
376 srclen
= crp
->crp_ilen
;
378 pasemi_desc_start(&work_desc
, XCT_FUN_O
| XCT_FUN_I
379 | XCT_FUN_FUN(chsel
));
380 if (enccrd
->crd_flags
& CRD_F_ENCRYPT
)
381 pasemi_desc_hdr(&work_desc
, XCT_FUN_CRM_ENC
);
383 pasemi_desc_hdr(&work_desc
, XCT_FUN_CRM_DEC
);
384 } else if (enccrd
&& maccrd
) {
385 if (enccrd
->crd_alg
== CRYPTO_ARC4
)
389 if (enccrd
->crd_flags
& CRD_F_ENCRYPT
) {
390 /* Encrypt -> Authenticate */
391 pasemi_desc_start(&work_desc
, XCT_FUN_O
| XCT_FUN_I
| XCT_FUN_CRM_ENC_SIG
392 | XCT_FUN_A
| XCT_FUN_FUN(chsel
));
393 srclen
= maccrd
->crd_skip
+ maccrd
->crd_len
;
395 /* Authenticate -> Decrypt */
396 pasemi_desc_start(&work_desc
, XCT_FUN_O
| XCT_FUN_I
| XCT_FUN_CRM_SIG_DEC
397 | XCT_FUN_24BRES
| XCT_FUN_FUN(chsel
));
398 pasemi_desc_build(&work_desc
, 0);
399 pasemi_desc_build(&work_desc
, 0);
400 pasemi_desc_build(&work_desc
, 0);
401 work_desc
.postop
= PASEMI_CHECK_SIG
;
402 srclen
= crp
->crp_ilen
;
405 pasemi_desc_hdr(&work_desc
, XCT_FUN_SHL(maccrd
->crd_skip
/ 4));
406 pasemi_desc_hdr(&work_desc
, XCT_FUN_CHL(enccrd
->crd_skip
- maccrd
->crd_skip
));
407 } else if (!enccrd
&& maccrd
) {
408 srclen
= maccrd
->crd_len
;
410 pasemi_desc_start(&init_desc
,
411 XCT_CTRL_HDR(chsel
, 0x58, DMA_FN_HKEY0
));
412 pasemi_desc_build(&init_desc
,
413 XCT_FUN_SRC_PTR(0x58, ((struct pasemi_session
*)ses
->dma_addr
)->hkey
));
415 pasemi_desc_start(&work_desc
, XCT_FUN_O
| XCT_FUN_I
| XCT_FUN_CRM_SIG
416 | XCT_FUN_A
| XCT_FUN_FUN(chsel
));
420 switch (enccrd
->crd_alg
) {
421 case CRYPTO_3DES_CBC
:
422 pasemi_desc_hdr(&work_desc
, XCT_FUN_ALG_3DES
|
424 ivsize
= sizeof(u64
);
427 pasemi_desc_hdr(&work_desc
, XCT_FUN_ALG_DES
|
429 ivsize
= sizeof(u64
);
432 pasemi_desc_hdr(&work_desc
, XCT_FUN_ALG_AES
|
434 ivsize
= 2 * sizeof(u64
);
437 pasemi_desc_hdr(&work_desc
, XCT_FUN_ALG_ARC
);
441 printk(DRV_NAME
": unimplemented enccrd->crd_alg %d\n",
447 ivp
= (ivsize
== sizeof(u64
)) ? (caddr_t
) &ses
->civ
[1] : (caddr_t
) &ses
->civ
[0];
448 if (enccrd
->crd_flags
& CRD_F_ENCRYPT
) {
449 if (enccrd
->crd_flags
& CRD_F_IV_EXPLICIT
)
450 memcpy(ivp
, enccrd
->crd_iv
, ivsize
);
451 /* If IV is not present in the buffer already, it has to be copied there */
452 if ((enccrd
->crd_flags
& CRD_F_IV_PRESENT
) == 0)
453 crypto_copyback(crp
->crp_flags
, crp
->crp_buf
,
454 enccrd
->crd_inject
, ivsize
, ivp
);
456 if (enccrd
->crd_flags
& CRD_F_IV_EXPLICIT
)
457 /* IV is provided expicitly in descriptor */
458 memcpy(ivp
, enccrd
->crd_iv
, ivsize
);
460 /* IV is provided in the packet */
461 crypto_copydata(crp
->crp_flags
, crp
->crp_buf
,
462 enccrd
->crd_inject
, ivsize
,
468 switch (maccrd
->crd_alg
) {
470 pasemi_desc_hdr(&work_desc
, XCT_FUN_SIG_MD5
|
471 XCT_FUN_HSZ((crp
->crp_ilen
- maccrd
->crd_inject
) / 4));
474 pasemi_desc_hdr(&work_desc
, XCT_FUN_SIG_SHA1
|
475 XCT_FUN_HSZ((crp
->crp_ilen
- maccrd
->crd_inject
) / 4));
477 case CRYPTO_MD5_HMAC
:
478 pasemi_desc_hdr(&work_desc
, XCT_FUN_SIG_HMAC_MD5
|
479 XCT_FUN_HSZ((crp
->crp_ilen
- maccrd
->crd_inject
) / 4));
481 case CRYPTO_SHA1_HMAC
:
482 pasemi_desc_hdr(&work_desc
, XCT_FUN_SIG_HMAC_SHA1
|
483 XCT_FUN_HSZ((crp
->crp_ilen
- maccrd
->crd_inject
) / 4));
486 printk(DRV_NAME
": unimplemented maccrd->crd_alg %d\n",
493 if (crp
->crp_flags
& CRYPTO_F_SKBUF
) {
494 /* using SKB buffers */
495 skb
= (struct sk_buff
*)crp
->crp_buf
;
496 if (skb_shinfo(skb
)->nr_frags
) {
497 printk(DRV_NAME
": skb frags unimplemented\n");
503 XCT_FUN_DST_PTR(skb
->len
, pci_map_single(
504 sc
->dma_pdev
, skb
->data
,
505 skb
->len
, DMA_TO_DEVICE
)));
509 srclen
, pci_map_single(
510 sc
->dma_pdev
, skb
->data
,
511 srclen
, DMA_TO_DEVICE
)));
512 pasemi_desc_hdr(&work_desc
, XCT_FUN_LLEN(srclen
));
513 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
514 /* using IOV buffers */
515 uiop
= (struct uio
*)crp
->crp_buf
;
516 if (uiop
->uio_iovcnt
> 1) {
517 printk(DRV_NAME
": iov frags unimplemented\n");
522 /* crp_olen is never set; always use crp_ilen */
525 XCT_FUN_DST_PTR(crp
->crp_ilen
, pci_map_single(
527 uiop
->uio_iov
->iov_base
,
528 crp
->crp_ilen
, DMA_TO_DEVICE
)));
529 pasemi_desc_hdr(&work_desc
, XCT_FUN_LLEN(srclen
));
533 XCT_FUN_SRC_PTR(srclen
, pci_map_single(
535 uiop
->uio_iov
->iov_base
,
536 srclen
, DMA_TO_DEVICE
)));
538 /* using contig buffers */
541 XCT_FUN_DST_PTR(crp
->crp_ilen
, pci_map_single(
544 crp
->crp_ilen
, DMA_TO_DEVICE
)));
547 XCT_FUN_SRC_PTR(srclen
, pci_map_single(
549 crp
->crp_buf
, srclen
,
551 pasemi_desc_hdr(&work_desc
, XCT_FUN_LLEN(srclen
));
554 spin_lock_irqsave(&txring
->fill_lock
, flags
);
556 if (txring
->sesn
!= PASEMI_SESSION(crp
->crp_sid
)) {
557 txring
->sesn
= PASEMI_SESSION(crp
->crp_sid
);
562 pasemi_desc_start(&init_desc
,
563 XCT_CTRL_HDR(chsel
, reinit
? reinit_size
: 0x10, DMA_FN_CIV0
));
564 pasemi_desc_build(&init_desc
,
565 XCT_FUN_SRC_PTR(reinit
? reinit_size
: 0x10, ses
->dma_addr
));
568 if (((txring
->next_to_fill
+ pasemi_desc_size(&init_desc
) +
569 pasemi_desc_size(&work_desc
)) -
570 txring
->next_to_clean
) > TX_RING_SIZE
) {
571 spin_unlock_irqrestore(&txring
->fill_lock
, flags
);
576 pasemi_ring_add_desc(txring
, &init_desc
, NULL
);
577 pasemi_ring_add_desc(txring
, &work_desc
, crp
);
579 pasemi_ring_incr(sc
, chsel
,
580 pasemi_desc_size(&init_desc
) +
581 pasemi_desc_size(&work_desc
));
583 spin_unlock_irqrestore(&txring
->fill_lock
, flags
);
585 mod_timer(&txring
->crypto_timer
, jiffies
+ TIMER_INTERVAL
);
590 printk(DRV_NAME
": unsupported algorithm or algorithm order alg1 %d alg2 %d\n",
591 crd1
->crd_alg
, crd2
->crd_alg
);
595 if (err
!= ERESTART
) {
596 crp
->crp_etype
= err
;
602 static int pasemi_clean_tx(struct pasemi_softc
*sc
, int chan
)
605 struct pasemi_fnu_txring
*ring
= &sc
->tx
[chan
];
607 int flags
, loops
= 10;
611 spin_lock_irqsave(&ring
->clean_lock
, flags
);
613 while ((delta_cnt
= (dma_status
->tx_sta
[sc
->base_chan
+ chan
]
614 & PAS_STATUS_PCNT_M
) - ring
->total_pktcnt
)
617 for (i
= 0; i
< delta_cnt
; i
++) {
618 desc_size
= TX_DESC_INFO(ring
, ring
->next_to_clean
).desc_size
;
619 crp
= TX_DESC_INFO(ring
, ring
->next_to_clean
).cf_crp
;
621 ring_idx
= 2 * (ring
->next_to_clean
& (TX_RING_SIZE
-1));
622 if (TX_DESC_INFO(ring
, ring
->next_to_clean
).desc_postop
& PASEMI_CHECK_SIG
) {
623 /* Need to make sure signature matched,
624 * if not - return error */
625 if (!(ring
->desc
[ring_idx
+ 1] & (1ULL << 63)))
626 crp
->crp_etype
= -EINVAL
;
628 crypto_done(TX_DESC_INFO(ring
,
629 ring
->next_to_clean
).cf_crp
);
630 TX_DESC_INFO(ring
, ring
->next_to_clean
).cf_crp
= NULL
;
633 XCT_PTR_ADDR_LEN(ring
->desc
[ring_idx
+ 1]),
636 ring
->desc
[ring_idx
] = ring
->desc
[ring_idx
+ 1] = 0;
638 ring
->next_to_clean
++;
639 for (j
= 1; j
< desc_size
; j
++) {
641 (ring
->next_to_clean
&
645 XCT_PTR_ADDR_LEN(ring
->desc
[ring_idx
]),
647 if (ring
->desc
[ring_idx
+ 1])
654 ring
->desc
[ring_idx
] =
655 ring
->desc
[ring_idx
+ 1] = 0;
656 ring
->next_to_clean
++;
659 for (j
= 0; j
< desc_size
; j
++) {
660 ring_idx
= 2 * (ring
->next_to_clean
& (TX_RING_SIZE
-1));
661 ring
->desc
[ring_idx
] =
662 ring
->desc
[ring_idx
+ 1] = 0;
663 ring
->next_to_clean
++;
668 ring
->total_pktcnt
+= delta_cnt
;
670 spin_unlock_irqrestore(&ring
->clean_lock
, flags
);
675 static void sweepup_tx(struct pasemi_softc
*sc
)
679 for (i
= 0; i
< sc
->sc_num_channels
; i
++)
680 pasemi_clean_tx(sc
, i
);
683 static irqreturn_t
pasemi_intr(int irq
, void *arg
, struct pt_regs
*regs
)
685 struct pasemi_softc
*sc
= arg
;
687 int chan
= irq
- sc
->base_irq
;
688 int chan_index
= sc
->base_chan
+ chan
;
689 u64 stat
= dma_status
->tx_sta
[chan_index
];
691 DPRINTF("%s()\n", __FUNCTION__
);
693 if (!(stat
& PAS_STATUS_CAUSE_M
))
696 pasemi_clean_tx(sc
, chan
);
698 stat
= dma_status
->tx_sta
[chan_index
];
700 reg
= PAS_IOB_DMA_TXCH_RESET_PINTC
|
701 PAS_IOB_DMA_TXCH_RESET_PCNT(sc
->tx
[chan
].total_pktcnt
);
703 if (stat
& PAS_STATUS_SOFT
)
704 reg
|= PAS_IOB_DMA_RXCH_RESET_SINTC
;
706 out_le32(sc
->iob_regs
+ PAS_IOB_DMA_TXCH_RESET(chan_index
), reg
);
712 static int pasemi_dma_setup_tx_resources(struct pasemi_softc
*sc
, int chan
)
715 int chan_index
= chan
+ sc
->base_chan
;
717 struct pasemi_fnu_txring
*ring
;
719 ring
= &sc
->tx
[chan
];
721 spin_lock_init(&ring
->fill_lock
);
722 spin_lock_init(&ring
->clean_lock
);
724 ring
->desc_info
= kzalloc(sizeof(struct pasemi_desc_info
) *
725 TX_RING_SIZE
, GFP_KERNEL
);
726 if (!ring
->desc_info
)
729 /* Allocate descriptors */
730 ring
->desc
= dma_alloc_coherent(&sc
->dma_pdev
->dev
,
733 &ring
->dma
, GFP_KERNEL
);
737 memset((void *) ring
->desc
, 0, TX_RING_SIZE
* 2 * sizeof(u64
));
739 out_le32(sc
->iob_regs
+ PAS_IOB_DMA_TXCH_RESET(chan_index
), 0x30);
741 ring
->total_pktcnt
= 0;
743 out_le32(sc
->dma_regs
+ PAS_DMA_TXCHAN_BASEL(chan_index
),
744 PAS_DMA_TXCHAN_BASEL_BRBL(ring
->dma
));
746 val
= PAS_DMA_TXCHAN_BASEU_BRBH(ring
->dma
>> 32);
747 val
|= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE
>> 2);
749 out_le32(sc
->dma_regs
+ PAS_DMA_TXCHAN_BASEU(chan_index
), val
);
751 out_le32(sc
->dma_regs
+ PAS_DMA_TXCHAN_CFG(chan_index
),
752 PAS_DMA_TXCHAN_CFG_TY_FUNC
|
753 PAS_DMA_TXCHAN_CFG_TATTR(chan
) |
754 PAS_DMA_TXCHAN_CFG_WT(2));
756 /* enable tx channel */
757 out_le32(sc
->dma_regs
+
758 PAS_DMA_TXCHAN_TCMDSTA(chan_index
),
759 PAS_DMA_TXCHAN_TCMDSTA_EN
);
761 out_le32(sc
->iob_regs
+ PAS_IOB_DMA_TXCH_CFG(chan_index
),
762 PAS_IOB_DMA_TXCH_CFG_CNTTH(1000));
764 ring
->next_to_fill
= 0;
765 ring
->next_to_clean
= 0;
767 snprintf(ring
->irq_name
, sizeof(ring
->irq_name
),
768 "%s%d", "crypto", chan
);
770 ring
->irq
= irq_create_mapping(NULL
, sc
->base_irq
+ chan
);
771 ret
= request_irq(ring
->irq
, (irq_handler_t
)
772 pasemi_intr
, IRQF_DISABLED
, ring
->irq_name
, sc
);
774 printk(KERN_ERR DRV_NAME
": failed to hook irq %d ret %d\n",
780 setup_timer(&ring
->crypto_timer
, (void *) sweepup_tx
, (unsigned long) sc
);
785 static device_method_t pasemi_methods
= {
786 /* crypto device methods */
787 DEVMETHOD(cryptodev_newsession
, pasemi_newsession
),
788 DEVMETHOD(cryptodev_freesession
, pasemi_freesession
),
789 DEVMETHOD(cryptodev_process
, pasemi_process
),
792 /* Set up the crypto device structure, private data,
793 * and anything else we need before we start */
796 pasemi_dma_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
798 struct pasemi_softc
*sc
;
801 DPRINTF(KERN_ERR
"%s()\n", __FUNCTION__
);
803 sc
= kzalloc(sizeof(*sc
), GFP_KERNEL
);
807 softc_device_init(sc
, DRV_NAME
, 1, pasemi_methods
);
809 pci_set_drvdata(pdev
, sc
);
811 spin_lock_init(&sc
->sc_chnlock
);
813 sc
->sc_sessions
= (struct pasemi_session
**)
814 kzalloc(PASEMI_INITIAL_SESSIONS
*
815 sizeof(struct pasemi_session
*), GFP_ATOMIC
);
816 if (sc
->sc_sessions
== NULL
) {
821 sc
->sc_nsessions
= PASEMI_INITIAL_SESSIONS
;
823 sc
->base_irq
= pdev
->irq
+ 6;
828 sc
->iob_pdev
= pci_get_device(PCI_VENDOR_ID_PASEMI
, 0xa001, NULL
);
830 dev_err(&pdev
->dev
, "Can't find I/O Bridge\n");
835 /* This is hardcoded and ugly, but we have some firmware versions
836 * who don't provide the register space in the device tree. Luckily
837 * they are at well-known locations so we can just do the math here.
840 ioremap(0xe0000000 + (sc
->dma_pdev
->devfn
<< 12), 0x2000);
842 ioremap(0xe0000000 + (sc
->iob_pdev
->devfn
<< 12), 0x2000);
843 if (!sc
->dma_regs
|| !sc
->iob_regs
) {
844 dev_err(&pdev
->dev
, "Can't map registers\n");
849 dma_status
= __ioremap(0xfd800000, 0x1000, 0);
852 dev_err(&pdev
->dev
, "Can't map dmastatus space\n");
856 sc
->tx
= (struct pasemi_fnu_txring
*)
857 kzalloc(sizeof(struct pasemi_fnu_txring
)
864 /* Initialize the h/w */
865 out_le32(sc
->dma_regs
+ PAS_DMA_COM_CFG
,
866 (in_le32(sc
->dma_regs
+ PAS_DMA_COM_CFG
) |
867 PAS_DMA_COM_CFG_FWF
));
868 out_le32(sc
->dma_regs
+ PAS_DMA_COM_TXCMD
, PAS_DMA_COM_TXCMD_EN
);
870 for (i
= 0; i
< PASEMI_FNU_CHANNELS
; i
++) {
871 sc
->sc_num_channels
++;
872 ret
= pasemi_dma_setup_tx_resources(sc
, i
);
877 sc
->sc_cid
= crypto_get_driverid(softc_get_device(sc
),
878 CRYPTOCAP_F_HARDWARE
);
879 if (sc
->sc_cid
< 0) {
880 printk(KERN_ERR DRV_NAME
": could not get crypto driver id\n");
885 /* register algorithms with the framework */
886 printk(DRV_NAME
":");
888 crypto_register(sc
->sc_cid
, CRYPTO_DES_CBC
, 0, 0);
889 crypto_register(sc
->sc_cid
, CRYPTO_3DES_CBC
, 0, 0);
890 crypto_register(sc
->sc_cid
, CRYPTO_AES_CBC
, 0, 0);
891 crypto_register(sc
->sc_cid
, CRYPTO_ARC4
, 0, 0);
892 crypto_register(sc
->sc_cid
, CRYPTO_SHA1
, 0, 0);
893 crypto_register(sc
->sc_cid
, CRYPTO_MD5
, 0, 0);
894 crypto_register(sc
->sc_cid
, CRYPTO_SHA1_HMAC
, 0, 0);
895 crypto_register(sc
->sc_cid
, CRYPTO_MD5_HMAC
, 0, 0);
900 pasemi_dma_remove(pdev
);
904 #define MAX_RETRIES 5000
906 static void pasemi_free_tx_resources(struct pasemi_softc
*sc
, int chan
)
908 struct pasemi_fnu_txring
*ring
= &sc
->tx
[chan
];
909 int chan_index
= chan
+ sc
->base_chan
;
913 /* Stop the channel */
914 out_le32(sc
->dma_regs
+
915 PAS_DMA_TXCHAN_TCMDSTA(chan_index
),
916 PAS_DMA_TXCHAN_TCMDSTA_ST
);
918 for (retries
= 0; retries
< MAX_RETRIES
; retries
++) {
919 stat
= in_le32(sc
->dma_regs
+
920 PAS_DMA_TXCHAN_TCMDSTA(chan_index
));
921 if (!(stat
& PAS_DMA_TXCHAN_TCMDSTA_ACT
))
926 if (stat
& PAS_DMA_TXCHAN_TCMDSTA_ACT
)
927 dev_err(&sc
->dma_pdev
->dev
, "Failed to stop tx channel %d\n",
930 /* Disable the channel */
931 out_le32(sc
->dma_regs
+
932 PAS_DMA_TXCHAN_TCMDSTA(chan_index
),
936 kfree((void *) ring
->desc_info
);
938 dma_free_coherent(&sc
->dma_pdev
->dev
,
941 (void *) ring
->desc
, ring
->dma
);
943 free_irq(ring
->irq
, sc
);
945 del_timer(&ring
->crypto_timer
);
948 static void __devexit
pasemi_dma_remove(struct pci_dev
*pdev
)
950 struct pasemi_softc
*sc
= pci_get_drvdata(pdev
);
953 DPRINTF("%s()\n", __FUNCTION__
);
955 if (sc
->sc_cid
>= 0) {
956 crypto_unregister_all(sc
->sc_cid
);
960 for (i
= 0; i
< sc
->sc_num_channels
; i
++)
961 pasemi_free_tx_resources(sc
, i
);
965 if (sc
->sc_sessions
) {
966 for (i
= 0; i
< sc
->sc_nsessions
; i
++)
967 kfree(sc
->sc_sessions
[i
]);
968 kfree(sc
->sc_sessions
);
971 pci_dev_put(sc
->iob_pdev
);
973 iounmap(sc
->dma_regs
);
975 iounmap(sc
->iob_regs
);
979 static struct pci_device_id pasemi_dma_pci_tbl
[] = {
980 { PCI_DEVICE(PCI_VENDOR_ID_PASEMI
, 0xa007) },
983 MODULE_DEVICE_TABLE(pci
, pasemi_dma_pci_tbl
);
985 static struct pci_driver pasemi_dma_driver
= {
986 .name
= "pasemi_dma",
987 .id_table
= pasemi_dma_pci_tbl
,
988 .probe
= pasemi_dma_probe
,
989 .remove
= __devexit_p(pasemi_dma_remove
),
992 static void __exit
pasemi_dma_cleanup_module(void)
994 pci_unregister_driver(&pasemi_dma_driver
);
995 __iounmap(dma_status
);
999 int pasemi_dma_init_module(void)
1001 return pci_register_driver(&pasemi_dma_driver
);
1004 module_init(pasemi_dma_init_module
);
1005 module_exit(pasemi_dma_cleanup_module
);
1007 MODULE_LICENSE("Dual BSD/GPL");
1008 MODULE_AUTHOR("Egor Martovetsky egor@pasemi.com");
1009 MODULE_DESCRIPTION("OCF driver for PA Semi PWRficient DMA Crypto Engine");