mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
crypto: virtio - 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: 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>
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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))
|
||||||
|
|||||||
Reference in New Issue
Block a user