Commit fa2e6947 authored by zhenwei pi's avatar zhenwei pi Committed by Michael S. Tsirkin

virtio-crypto: handle config changed by work queue

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: default avatarzhenwei pi <pizhenwei@bytedance.com>
Message-Id: <20231007064309.844889-1-pizhenwei@bytedance.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent ca50ec37
...@@ -35,6 +35,9 @@ struct virtio_crypto { ...@@ -35,6 +35,9 @@ struct virtio_crypto {
struct virtqueue *ctrl_vq; struct virtqueue *ctrl_vq;
struct data_queue *data_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 */ /* To protect the vq operations for the controlq */
spinlock_t ctrl_lock; spinlock_t ctrl_lock;
......
...@@ -335,6 +335,14 @@ static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto) ...@@ -335,6 +335,14 @@ static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto)
virtcrypto_free_queues(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) static int virtcrypto_probe(struct virtio_device *vdev)
{ {
int err = -EFAULT; int err = -EFAULT;
...@@ -454,6 +462,8 @@ static int virtcrypto_probe(struct virtio_device *vdev) ...@@ -454,6 +462,8 @@ static int virtcrypto_probe(struct virtio_device *vdev)
if (err) if (err)
goto free_engines; goto free_engines;
INIT_WORK(&vcrypto->config_work, vcrypto_config_changed_work);
return 0; return 0;
free_engines: free_engines:
...@@ -490,6 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev) ...@@ -490,6 +500,7 @@ static void virtcrypto_remove(struct virtio_device *vdev)
dev_info(&vdev->dev, "Start virtcrypto_remove.\n"); dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
flush_work(&vcrypto->config_work);
if (virtcrypto_dev_started(vcrypto)) if (virtcrypto_dev_started(vcrypto))
virtcrypto_dev_stop(vcrypto); virtcrypto_dev_stop(vcrypto);
virtio_reset_device(vdev); virtio_reset_device(vdev);
...@@ -504,7 +515,7 @@ static void virtcrypto_config_changed(struct virtio_device *vdev) ...@@ -504,7 +515,7 @@ static void virtcrypto_config_changed(struct virtio_device *vdev)
{ {
struct virtio_crypto *vcrypto = vdev->priv; struct virtio_crypto *vcrypto = vdev->priv;
virtcrypto_update_status(vcrypto); schedule_work(&vcrypto->config_work);
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -512,6 +523,7 @@ static int virtcrypto_freeze(struct virtio_device *vdev) ...@@ -512,6 +523,7 @@ static int virtcrypto_freeze(struct virtio_device *vdev)
{ {
struct virtio_crypto *vcrypto = vdev->priv; struct virtio_crypto *vcrypto = vdev->priv;
flush_work(&vcrypto->config_work);
virtio_reset_device(vdev); virtio_reset_device(vdev);
virtcrypto_free_unused_reqs(vcrypto); virtcrypto_free_unused_reqs(vcrypto);
if (virtcrypto_dev_started(vcrypto)) if (virtcrypto_dev_started(vcrypto))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment