crypto: virtio - Handle dataq logic with tasklet
[ Upstream commit fed93fb62e05c38152b0fc1dc9609639e63eed76 ] 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: dbaf0624ffa57 ("crypto: add virtio-crypto driver") Reported-by: Halil Pasic <pasic@linux.ibm.com> Signed-off-by: wangyangxin <wangyangxin1@huawei.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
d4b65d3072
commit
28722ef6cb
2 changed files with 15 additions and 10 deletions
|
@ -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 {
|
||||||
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
|
||||||
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)
|
||||||
|
@ -149,6 +150,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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue