Commit fed93fb6 authored by Gonglei (Arei)'s avatar Gonglei (Arei) Committed by Herbert Xu

crypto: virtio - Handle dataq logic with tasklet

Doing ipsec produces a spinlock recursion warning.
This is due to crypto_finalize_request() being called in the upper half.
Move virtual data queue processing of virtio-crypto driver to tasklet.

Fixes: dbaf0624 ("crypto: add virtio-crypto driver")
Reported-by: default avatarHalil Pasic <pasic@linux.ibm.com>
Signed-off-by: default avatarwangyangxin <wangyangxin1@huawei.com>
Signed-off-by: default avatarGonglei <arei.gonglei@huawei.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 8a0d929b
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/virtio.h> #include <linux/virtio.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <crypto/aead.h> #include <crypto/aead.h>
#include <crypto/aes.h> #include <crypto/aes.h>
#include <crypto/engine.h> #include <crypto/engine.h>
...@@ -28,6 +29,7 @@ struct data_queue { ...@@ -28,6 +29,7 @@ struct data_queue {
char name[32]; char name[32];
struct crypto_engine *engine; struct crypto_engine *engine;
struct tasklet_struct done_task;
}; };
struct virtio_crypto { struct virtio_crypto {
......
...@@ -72,27 +72,28 @@ int virtio_crypto_ctrl_vq_request(struct virtio_crypto *vcrypto, struct scatterl ...@@ -72,27 +72,28 @@ int virtio_crypto_ctrl_vq_request(struct virtio_crypto *vcrypto, struct scatterl
return 0; return 0;
} }
static void virtcrypto_dataq_callback(struct virtqueue *vq) static void virtcrypto_done_task(unsigned long data)
{ {
struct virtio_crypto *vcrypto = vq->vdev->priv; struct data_queue *data_vq = (struct data_queue *)data;
struct virtqueue *vq = data_vq->vq;
struct virtio_crypto_request *vc_req; struct virtio_crypto_request *vc_req;
unsigned long flags;
unsigned int len; unsigned int len;
unsigned int qid = vq->index;
spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags);
do { do {
virtqueue_disable_cb(vq); virtqueue_disable_cb(vq);
while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) { while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
spin_unlock_irqrestore(
&vcrypto->data_vq[qid].lock, flags);
if (vc_req->alg_cb) if (vc_req->alg_cb)
vc_req->alg_cb(vc_req, len); vc_req->alg_cb(vc_req, len);
spin_lock_irqsave(
&vcrypto->data_vq[qid].lock, flags);
} }
} while (!virtqueue_enable_cb(vq)); } while (!virtqueue_enable_cb(vq));
spin_unlock_irqrestore(&vcrypto->data_vq[qid].lock, flags); }
static void virtcrypto_dataq_callback(struct virtqueue *vq)
{
struct virtio_crypto *vcrypto = vq->vdev->priv;
struct data_queue *dq = &vcrypto->data_vq[vq->index];
tasklet_schedule(&dq->done_task);
} }
static int virtcrypto_find_vqs(struct virtio_crypto *vi) static int virtcrypto_find_vqs(struct virtio_crypto *vi)
...@@ -150,6 +151,8 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi) ...@@ -150,6 +151,8 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi)
ret = -ENOMEM; ret = -ENOMEM;
goto err_engine; goto err_engine;
} }
tasklet_init(&vi->data_vq[i].done_task, virtcrypto_done_task,
(unsigned long)&vi->data_vq[i]);
} }
kfree(names); kfree(names);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment