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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;

+13 −1
Original line number Diff line number Diff line
@@ -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))