first IDMA support for the Orion/CESA engine
Subsystems (4)
cover first IDMA support for the Orion/CESA engine
This is the first shot of DMA support for CESA on Orion. Right now, the IDMA engine is used as memcpy(), no descriptors are used yet. The DMA support seems to work fine so far. However it seems not to improve the performance that much I hoped in first place.
The second patch replaces the driver thread with an interrupt thread. I hacked it very quick together, it compiled and dm-crypt didn't complain. I hope that the latency between "interrupt" and "copy back" is as short as possible and maybe the performance improves a little :) I want to avoid to push everything into the raw interrupt handler.
The next step would be to implement correct DMA-descriptor support and let IDMA trigger CESA. Since CESA's ch0 has to work with IDMA's ch0 I don't think it makes much sense to go through the dmaengine framework. That's why I moved it to the crypto folder. IDMA's ch2 and ch3 could be exposed to the dmaengine framework if one likes but the XOR engine provides the same functionality.
Does someone have any objections on the idma-cesa mix? I probably should add some hooks for the dma engine in case Kirkwood's and Orion's HW is different here.
I'm off the radar for the next weeks so I can't reply.
- [RFC 1/2] crypto/cesa: add idma for Orion5X support also in branch orion_dma at [0]
- [RFC 2/2] crypto/mv-cesa: use threaded interrupts also available in branch orion_threaded_irq at [0]
[0] git://git.breakpoint.cc/bigeasy/linux.git
Sebastian
RFC 1/2 crypto/cesa: add idma for Orion5X support
From: Sebastian Siewior <[email protected]>
This patch adds iDMA support and wires up the CESA engine
--- arch/arm/include/asm/idma.h | 15 ++ arch/arm/mach-orion5x/addr-map.c | 11 + arch/arm/mach-orion5x/common.c | 45 +++++ arch/arm/mach-orion5x/common.h | 3 + arch/arm/mach-orion5x/include/mach/orion5x.h | 1 + drivers/crypto/Kconfig | 5 + drivers/crypto/Makefile | 1 + drivers/crypto/mv_cesa.c | 144 +++++++++++---- drivers/crypto/mv_idma.c | 259 ++++++++++++++++++++++++++ 9 files changed, 446 insertions(+), 38 deletions(-) create mode 100644 arch/arm/include/asm/idma.h create mode 100644 drivers/crypto/mv_idma.c
arch/arm/include/asm/idma.h new file +15 -0
@@ -0,0 +1,15 @@ +#ifndef __ASMARM_IDMA__ +#define __ASMARM_IDMA__ + +struct cesa_sram_info { +unsigned int target_id; +unsigned int attr; +unsigned int base; +}; + +struct idma_pdata { +struct cesa_sram_info *sram; +struct mbus_dram_target_info *dram; +}; + +#endif
arch/arm/mach-orion5x/addr-map.c +11 -0
@@ -75,6 +75,17 @@struct mbus_dram_target_info orion5x_mbus_dram_info; +struct cesa_sram_info orion5x_sram_info = { +/* Form some reason it is different than for the CPU. Ask me why */ +#if 0 + .target_id =TARGET_SRAM , + .attr =ATTR_SRAM , +#endif + .target_id =5 , + .attr =0 , + .base =ORION5X_SRAM_PHYS_BASE , +}; +static int __initdata win_alloc_count;static int __init orion5x_cpu_win_can_remap (int win)
arch/arm/mach-orion5x/common.c +45 -0
63 lines not on this page · raw message
arch/arm/mach-orion5x/common.h +3 -0
@@ -1,5 +1,6 @@#ifndef __ARCH_ORION5X_COMMON_H#define __ARCH_ORION5X_COMMON_H +#include <asm/idma.h> struct dsa_platform_data ;struct mv643xx_eth_platform_data ;
@@ -20,6 +21,8 @@ extern struct sys_timer orion5x_timer;* board devices. Details in /mach-orion/addr-map.c */ extern struct mbus_dram_target_info orion5x_mbus_dram_info; +extern struct cesa_sram_info orion5x_sram_info; +void orion5x_setup_cpu_mbus_bridge (void );void orion5x_setup_dev_boot_win (u32 base,u32 size);void orion5x_setup_dev0_win (u32 base,u32 size);
arch/arm/mach-orion5x/include/mach/orion5x.h +1 -0
@@ -99,6 +99,7 @@#define ORION5X_SATA_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x80000)#define ORION5X_CRYPTO_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x90000) +#define ORION5X_IDMA_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x60000)#define ORION5X_USB1_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0xa0000)#define ORION5X_USB1_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0xa0000)
drivers/crypto/Kconfig +5 -0
@@ -157,12 +157,17 @@ config S390_PRNG ANSI X9.17 standard. The PRNG is usable via the char device /dev/prandom. +config CRYPTO_DEV_MV_IDMA + tristate + depends on PLAT_ORION + config CRYPTO_DEV_MV_CESA tristate "Marvell's Cryptographic Engine" depends on PLAT_ORION select CRYPTO_ALGAPI select CRYPTO_AES select CRYPTO_BLKCIPHER2 + select CRYPTO_DEV_MV_IDMA help This driver allows you to utilize the Cryptographic Engines and Security Accelerator (CESA) which can be found on the Marvell Orion
drivers/crypto/Makefile +1 -0
@@ -2,6 +2,7 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o +obj-$(CONFIG_CRYPTO_DEV_MV_IDMA) += mv_idma.o obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
drivers/crypto/mv_cesa.c +106 -38
259 lines not on this page · raw message
drivers/crypto/mv_idma.c new file +259 -0
259 lines not on this page · raw message
Signature · 1 line
1.6.2.5
RFC 2/2 crypto/mv-cesa: use threaded interrupts
In reply to Sebastian A. SiewiorFrom: Sebastian Andrzej Siewior <[email protected]>
this patch converts the cesa-thread into a threaded-interrupt.
--- drivers/crypto/mv_cesa.c | 79 ++++++++++++++++----------------------------- 1 files changed, 28 insertions(+), 51 deletions(-)
drivers/crypto/mv_cesa.c +28 -51
@@ -60,7 +60,6 @@ struct crypto_priv {void __iomem *sram;u32 sram_phys;int irq; -struct task_struct *queue_th;/* the lock protects queue and eng_st */ spinlock_t lock;
@@ -317,52 +316,41 @@ static void mv_enqueue_new_req(struct ablkcipher_request *req)mv_process_current_q (1 ); } -static int queue_manag (void *data) +static irqreturn_t queue_manag (int irq,void *data) { - cpg->eng_st =ENGINE_IDLE ; -do { -struct ablkcipher_request *req; -struct crypto_async_request *async_req =NULL ; -struct crypto_async_request *backlog; - -__set_current_state (TASK_INTERRUPTIBLE ); - -if (cpg->eng_st ==ENGINE_W_DEQUEUE ) -dequeue_complete_req (); - -spin_lock_irq (&cpg->lock); -if (cpg->eng_st ==ENGINE_IDLE ) { - backlog =crypto_get_backlog (&cpg->queue); - async_req =crypto_dequeue_request (&cpg->queue); -if (async_req) { -BUG_ON (cpg->eng_st !=ENGINE_IDLE ); - cpg->eng_st =ENGINE_BUSY ; - } - } -spin_unlock_irq (&cpg->lock); +struct ablkcipher_request *req; +struct crypto_async_request *async_req =NULL ; +struct crypto_async_request *backlog =NULL ; -if (backlog) { - backlog->complete (backlog, -EINPROGRESS ); - backlog =NULL ; - } +if (cpg->eng_st ==ENGINE_W_DEQUEUE ) +dequeue_complete_req (); +spin_lock_bh (&cpg->lock); +if (cpg->eng_st ==ENGINE_IDLE ) { + backlog =crypto_get_backlog (&cpg->queue); + async_req =crypto_dequeue_request (&cpg->queue);if (async_req) { - req =container_of (async_req, - struct ablkcipher_request, base); -mv_enqueue_new_req (req); - async_req =NULL ; +BUG_ON (cpg->eng_st !=ENGINE_IDLE ); + cpg->eng_st =ENGINE_BUSY ; } + } +spin_unlock_bh (&cpg->lock); -schedule (); +if (backlog) + backlog->complete (backlog, -EINPROGRESS ); - }while (!kthread_should_stop ()); -return 0 ; +if (async_req) { + req =container_of (async_req, + struct ablkcipher_request, base); +mv_enqueue_new_req (req); + } + +return IRQ_HANDLED ; }static int mv_handle_req (struct ablkcipher_request *req) {struct mv_req_ctx *req_ctx =ablkcipher_request_ctx (req); -unsigned long flags;unsigned int n_sgs;int ret;int enqueue_plz =0 ;
@@ -408,7 +396,7 @@ static int mv_handle_req(struct ablkcipher_request *req) req_ctx->sg_dst_left =sg_dma_len (req->dst); } -spin_lock_irqsave (&cpg->lock, flags); +spin_lock_bh (&cpg->lock);/* If the engine is idle, we enqueue it on HW start processing. In the * other case we put in in the queue and enqueue it once we dequeue the * earlier request.
@@ -420,7 +408,7 @@ static int mv_handle_req(struct ablkcipher_request *req) }else { ret =ablkcipher_enqueue_request (&cpg->queue, req); } -spin_unlock_irqrestore (&cpg->lock, flags); +spin_unlock_bh (&cpg->lock);if (enqueue_plz)mv_enqueue_new_req (req);
@@ -491,8 +479,7 @@ irqreturn_t crypto_int(int irq, void *priv)writel (val, cpg->reg +SEC_ACCEL_INT_STATUS );BUG_ON (cpg->eng_st !=ENGINE_BUSY ); cpg->eng_st =ENGINE_W_DEQUEUE ; -wake_up_process (cpg->queue_th); -return IRQ_HANDLED ; +return IRQ_WAKE_THREAD ; }struct crypto_alg mv_aes_alg_ecb = {
@@ -591,15 +578,8 @@ static int mv_probe(struct platform_device *pdev)platform_set_drvdata (pdev, cp); cpg = cp; - - cp->queue_th =kthread_run (queue_manag, cp,"mv_crypto" ); -if (IS_ERR (cp->queue_th)) { - ret =PTR_ERR (cp->queue_th); - goto err_thread; - } - - ret =request_irq (irq, crypto_int,IRQF_DISABLED ,dev_name (&pdev->dev), - cp); + ret =request_threaded_irq (irq, crypto_int, queue_manag,0 , +dev_name (&pdev->dev), cp);if (ret) goto err_unmap_sram;
@@ -616,10 +596,8 @@ static int mv_probe(struct platform_device *pdev)return 0 ; err_unreg_ecb:crypto_unregister_alg (&mv_aes_alg_ecb); -err_thread:free_irq (irq, cp); err_reg: -kthread_stop (cp->queue_th); err_unmap_sram:iounmap (cp->sram); err_unmap_reg:
@@ -637,7 +615,6 @@ static int mv_remove(struct platform_device *pdev)crypto_unregister_alg (&mv_aes_alg_ecb);crypto_unregister_alg (&mv_aes_alg_cbc); -kthread_stop (cp->queue_th);free_irq (cp->irq, cp);memset (cp->sram,0 , cp->sram_size);iounmap (cp->sram);
Signature · 1 line
1.6.2.5