| From b66c5a84106d0c98d939aab5028c312e6d2aefcf Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 20 Nov 2023 11:49:45 +0000 |
| Subject: crypto: virtio - Handle dataq logic with tasklet |
| |
| From: Gonglei (Arei) <arei.gonglei@huawei.com> |
| |
| [ 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> |
| --- |
| drivers/crypto/virtio/virtio_crypto_common.h | 2 ++ |
| drivers/crypto/virtio/virtio_crypto_core.c | 23 +++++++++++--------- |
| 2 files changed, 15 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/crypto/virtio/virtio_crypto_common.h b/drivers/crypto/virtio/virtio_crypto_common.h |
| index 154590e1f764..7059bbe5a2eb 100644 |
| --- a/drivers/crypto/virtio/virtio_crypto_common.h |
| +++ b/drivers/crypto/virtio/virtio_crypto_common.h |
| @@ -10,6 +10,7 @@ |
| #include <linux/virtio.h> |
| #include <linux/crypto.h> |
| #include <linux/spinlock.h> |
| +#include <linux/interrupt.h> |
| #include <crypto/aead.h> |
| #include <crypto/aes.h> |
| #include <crypto/engine.h> |
| @@ -28,6 +29,7 @@ struct data_queue { |
| char name[32]; |
| |
| struct crypto_engine *engine; |
| + struct tasklet_struct done_task; |
| }; |
| |
| struct virtio_crypto { |
| diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c |
| index 43a0838d31ff..428d76562447 100644 |
| --- a/drivers/crypto/virtio/virtio_crypto_core.c |
| +++ b/drivers/crypto/virtio/virtio_crypto_core.c |
| @@ -72,27 +72,28 @@ int virtio_crypto_ctrl_vq_request(struct virtio_crypto *vcrypto, struct scatterl |
| 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; |
| - unsigned long flags; |
| unsigned int len; |
| - unsigned int qid = vq->index; |
| |
| - spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags); |
| do { |
| virtqueue_disable_cb(vq); |
| while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) { |
| - spin_unlock_irqrestore( |
| - &vcrypto->data_vq[qid].lock, flags); |
| if (vc_req->alg_cb) |
| vc_req->alg_cb(vc_req, len); |
| - spin_lock_irqsave( |
| - &vcrypto->data_vq[qid].lock, flags); |
| } |
| } 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) |
| @@ -150,6 +151,8 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi) |
| ret = -ENOMEM; |
| goto err_engine; |
| } |
| + tasklet_init(&vi->data_vq[i].done_task, virtcrypto_done_task, |
| + (unsigned long)&vi->data_vq[i]); |
| } |
| |
| kfree(names); |
| -- |
| 2.43.0 |
| |