crypto: virtio - handle config changed by work queue
authorzhenwei pi <pizhenwei@bytedance.com>
Sat, 7 Oct 2023 06:43:09 +0000 (14:43 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 20 Oct 2023 05:35:55 +0000 (13:35 +0800)
MST pointed out: config change callback is also handled incorrectly
in this driver, it takes a mutex from interrupt context.

Handle config changed by work queue instead.

Cc: Gonglei (Arei) <arei.gonglei@huawei.com>
Cc: Halil Pasic <pasic@linux.ibm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/virtio/virtio_crypto_common.h
drivers/crypto/virtio/virtio_crypto_core.c

index 59a4c02594563544c1ebaecf6a536487dc6adf54..154590e1f7643d60f21f0acb068abbdaba8c2e01 100644 (file)
@@ -35,6 +35,9 @@ struct virtio_crypto {
        struct virtqueue *ctrl_vq;
        struct data_queue *data_vq;
 
+       /* Work struct for config space updates */
+       struct work_struct config_work;
+
        /* To protect the vq operations for the controlq */
        spinlock_t ctrl_lock;
 
index 94849fa3bd74aaa85e7467a571b778e8e373417f..43a0838d31ff012129dabb11103e3a87c43d7242 100644 (file)
@@ -335,6 +335,14 @@ static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto)
        virtcrypto_free_queues(vcrypto);
 }
 
+static void vcrypto_config_changed_work(struct work_struct *work)
+{
+       struct virtio_crypto *vcrypto =
+               container_of(work, struct virtio_crypto, config_work);
+
+       virtcrypto_update_status(vcrypto);
+}
+
 static int virtcrypto_probe(struct virtio_device *vdev)
 {
        int err = -EFAULT;
@@ -454,6 +462,8 @@ static int virtcrypto_probe(struct virtio_device *vdev)
        if (err)
                goto free_engines;
 
+       INIT_WORK(&vcrypto->config_work, vcrypto_config_changed_work);
+
        return 0;
 
 free_engines:
@@ -490,6 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev)
 
        dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
 
+       flush_work(&vcrypto->config_work);
        if (virtcrypto_dev_started(vcrypto))
                virtcrypto_dev_stop(vcrypto);
        virtio_reset_device(vdev);
@@ -504,7 +515,7 @@ static void virtcrypto_config_changed(struct virtio_device *vdev)
 {
        struct virtio_crypto *vcrypto = vdev->priv;
 
-       virtcrypto_update_status(vcrypto);
+       schedule_work(&vcrypto->config_work);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -512,6 +523,7 @@ static int virtcrypto_freeze(struct virtio_device *vdev)
 {
        struct virtio_crypto *vcrypto = vdev->priv;
 
+       flush_work(&vcrypto->config_work);
        virtio_reset_device(vdev);
        virtcrypto_free_unused_reqs(vcrypto);
        if (virtcrypto_dev_started(vcrypto))