virtio-crypto: handle config changed by work queue
authorzhenwei pi <pizhenwei@bytedance.com>
Sat, 7 Oct 2023 06:43:09 +0000 (14:43 +0800)
committerMichael S. Tsirkin <mst@redhat.com>
Wed, 18 Oct 2023 15:30:06 +0000 (11:30 -0400)
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: stable@vger.kernel.org
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>
Message-Id: <20231007064309.844889-1-pizhenwei@bytedance.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/crypto/virtio/virtio_crypto_common.h
drivers/crypto/virtio/virtio_crypto_core.c

index 59a4c02..154590e 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 94849fa..43a0838 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))