virtio-crypto: handle config changed by work queue
authorzhenwei pi <pizhenwei@bytedance.com>
Sat, 7 Oct 2023 06:43:09 +0000 (14:43 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Nov 2023 08:35:23 +0000 (09:35 +0100)
commit fa2e6947aa8844f25f5bad0d8cd1a541d9bc83eb upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 1198bd3063655a87d7de886c7e9eecbd008d55ab..3842915ea7437748c2dd6f29898b1ed6ea0300bd 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:
@@ -489,6 +499,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);
@@ -503,7 +514,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
@@ -511,6 +522,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))