diff options
| author | Pat Somaru <patso@likewhatevs.io> | 2026-02-07 13:20:01 -0500 |
|---|---|---|
| committer | Herbert Xu <herbert@gondor.apana.org.au> | 2026-02-28 12:54:14 +0900 |
| commit | 2127a1bf8940ea76b4fc604fa6b5e4d734ca22ed (patch) | |
| tree | da0ec0cc021b989bde635413d619b11d721c76b0 | |
| parent | 404ba6b46b6e234384b962210a98931f7423f139 (diff) | |
crypto: virtio - Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context
is tasklet; however, it's marked deprecated and has some design flaws
such as the execution code accessing the tasklet item after the
execution is complete which can lead to subtle use-after-free in certain
usage scenarios and less-developed flush and cancel mechanisms.
To replace tasklets, BH workqueue support was recently added. A BH
workqueue behaves similarly to regular workqueues except that the queued
work items are executed in the BH context.
Convert virtio_crypto_core.c from tasklet to BH workqueue.
Semantically, this is an equivalent conversion and there shouldn't be
any user-visible behavior changes. The BH workqueue implementation uses
the same softirq infrastructure, and performance-critical networking
conversions have shown no measurable performance impact.
Signed-off-by: Pat Somaru <patso@likewhatevs.io>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
| -rw-r--r-- | drivers/crypto/virtio/virtio_crypto_common.h | 3 | ||||
| -rw-r--r-- | drivers/crypto/virtio/virtio_crypto_core.c | 11 |
2 files changed, 7 insertions, 7 deletions
diff --git a/drivers/crypto/virtio/virtio_crypto_common.h b/drivers/crypto/virtio/virtio_crypto_common.h index e559bdadf4f9..0c2efdc83257 100644 --- a/drivers/crypto/virtio/virtio_crypto_common.h +++ b/drivers/crypto/virtio/virtio_crypto_common.h @@ -11,6 +11,7 @@ #include <linux/crypto.h> #include <linux/spinlock.h> #include <linux/interrupt.h> +#include <linux/workqueue.h> #include <crypto/aead.h> #include <crypto/aes.h> #include <crypto/engine.h> @@ -29,7 +30,7 @@ struct data_queue { char name[32]; struct crypto_engine *engine; - struct tasklet_struct done_task; + struct work_struct done_work; }; struct virtio_crypto { diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c index 955bff8820da..ee83bf6568f0 100644 --- a/drivers/crypto/virtio/virtio_crypto_core.c +++ b/drivers/crypto/virtio/virtio_crypto_core.c @@ -70,9 +70,9 @@ int virtio_crypto_ctrl_vq_request(struct virtio_crypto *vcrypto, struct scatterl return 0; } -static void virtcrypto_done_task(unsigned long data) +static void virtcrypto_done_work(struct work_struct *work) { - struct data_queue *data_vq = (struct data_queue *)data; + struct data_queue *data_vq = from_work(data_vq, work, done_work); struct virtqueue *vq = data_vq->vq; struct virtio_crypto_request *vc_req; unsigned long flags; @@ -96,7 +96,7 @@ 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); + queue_work(system_bh_wq, &dq->done_work); } static int virtcrypto_find_vqs(struct virtio_crypto *vi) @@ -150,8 +150,7 @@ 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]); + INIT_WORK(&vi->data_vq[i].done_work, virtcrypto_done_work); } kfree(vqs_info); @@ -501,7 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev) if (virtcrypto_dev_started(vcrypto)) virtcrypto_dev_stop(vcrypto); for (i = 0; i < vcrypto->max_data_queues; i++) - tasklet_kill(&vcrypto->data_vq[i].done_task); + cancel_work_sync(&vcrypto->data_vq[i].done_work); virtio_reset_device(vdev); virtcrypto_free_unused_reqs(vcrypto); virtcrypto_clear_crypto_engines(vcrypto); |
