summaryrefslogtreecommitdiff
path: root/drivers/crypto/rockchip/rk3288_crypto.c
diff options
context:
space:
mode:
authorZain Wang <wzz@rock-chips.com>2017-08-15 15:48:15 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2017-08-22 14:54:54 +0800
commit5a7801f6634b1e2888bcb1a85bedc50e46dcd757 (patch)
tree8ce1aca11dfb13223b75f49efcdba7303e8c6805 /drivers/crypto/rockchip/rk3288_crypto.c
parentbaf5b752dae2b7c84b3fa5ffb0eb41648d659c09 (diff)
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 <wzz@rock-chips.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/rockchip/rk3288_crypto.c')
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.c46
1 files changed, 43 insertions, 3 deletions
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) {