From 5a7801f6634b1e2888bcb1a85bedc50e46dcd757 Mon Sep 17 00:00:00 2001 From: Zain Wang Date: Tue, 15 Aug 2017 15:48:15 +0800 Subject: crypto: rockchip - Don't dequeue the request when device is busy The device can only process one request at a time. So if multiple requests came at the same time, we can enqueue them first, and dequeue them one by one when the device is idle. Signed-off-by: zain wang Signed-off-by: Herbert Xu --- drivers/crypto/rockchip/rk3288_crypto.c | 46 ++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'drivers/crypto/rockchip/rk3288_crypto.c') diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index 57c37831bd42..c9d622abd90c 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -184,15 +184,53 @@ static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) return IRQ_HANDLED; } +static int rk_crypto_enqueue(struct rk_crypto_info *dev, + struct crypto_async_request *async_req) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&dev->lock, flags); + ret = crypto_enqueue_request(&dev->queue, async_req); + if (dev->busy) { + spin_unlock_irqrestore(&dev->lock, flags); + return ret; + } + dev->busy = true; + spin_unlock_irqrestore(&dev->lock, flags); + tasklet_schedule(&dev->queue_task); + + return ret; +} + static void rk_crypto_queue_task_cb(unsigned long data) { struct rk_crypto_info *dev = (struct rk_crypto_info *)data; + struct crypto_async_request *async_req, *backlog; + unsigned long flags; int err = 0; dev->err = 0; + spin_lock_irqsave(&dev->lock, flags); + backlog = crypto_get_backlog(&dev->queue); + async_req = crypto_dequeue_request(&dev->queue); + + if (!async_req) { + dev->busy = false; + spin_unlock_irqrestore(&dev->lock, flags); + return; + } + spin_unlock_irqrestore(&dev->lock, flags); + + if (backlog) { + backlog->complete(backlog, -EINPROGRESS); + backlog = NULL; + } + + dev->async_req = async_req; err = dev->start(dev); if (err) - dev->complete(dev, err); + dev->complete(dev->async_req, err); } static void rk_crypto_done_task_cb(unsigned long data) @@ -200,13 +238,13 @@ static void rk_crypto_done_task_cb(unsigned long data) struct rk_crypto_info *dev = (struct rk_crypto_info *)data; if (dev->err) { - dev->complete(dev, dev->err); + dev->complete(dev->async_req, dev->err); return; } dev->err = dev->update(dev); if (dev->err) - dev->complete(dev, dev->err); + dev->complete(dev->async_req, dev->err); } static struct rk_crypto_tmp *rk_cipher_algs[] = { @@ -365,6 +403,8 @@ static int rk_crypto_probe(struct platform_device *pdev) crypto_info->disable_clk = rk_crypto_disable_clk; crypto_info->load_data = rk_load_data; crypto_info->unload_data = rk_unload_data; + crypto_info->enqueue = rk_crypto_enqueue; + crypto_info->busy = false; err = rk_crypto_register(crypto_info); if (err) { -- cgit v1.2.3