The .remove() callback is not marked as optional for a virtio_driver,
and thus a missing one is a bug. Moreover, the virtio framework expects
a driver to reset the device it controls during teardown and explicitly
checks for this reading the device status and WARNing in case it is
still running. Any devm cleanup action gets however called after that
check, leading to the WARN_ON condition to always be true for
spi-virtio; thus, an empty remove() is not an option.
Move the cleanup actions to the .remove() callback of the driver and
adapt the surrounding code to the new behavior.
Fixes: f98cabe3f6cf ("SPI: Add virtio SPI driver")
Signed-off-by: Francesco Valla <[email protected]>
---
drivers/spi/spi-virtio.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi-virtio.c b/drivers/spi/spi-virtio.c
index 26f9711c99b3..2eeb79ff5aa2 100644
--- a/drivers/spi/spi-virtio.c
+++ b/drivers/spi/spi-virtio.c
@@ -315,10 +315,8 @@ static int virtio_spi_find_vqs(struct virtio_spi_priv
*priv)
}
/* Function must not be called before virtio_spi_find_vqs() has been run */
-static void virtio_spi_del_vq(void *data)
+static void virtio_spi_del_vq(struct virtio_device *vdev)
{
- struct virtio_device *vdev = data;
-
virtio_reset_device(vdev);
vdev->config->del_vqs(vdev);
}
@@ -347,21 +345,26 @@ static int virtio_spi_probe(struct virtio_device *vdev)
if (ret)
return dev_err_probe(&vdev->dev, ret, "Cannot setup
virtqueues\n");
- /* Register cleanup for virtqueues using devm */
- ret = devm_add_action_or_reset(&vdev->dev, virtio_spi_del_vq, vdev);
- if (ret)
- return dev_err_probe(&vdev->dev, ret, "Cannot register
virtqueue cleanup\n");
-
virtio_device_ready(vdev);
- /* Use devm version to register controller */
- ret = devm_spi_register_controller(&vdev->dev, ctrl);
- if (ret)
+ ret = spi_register_controller(ctrl);
+ if (ret) {
+ virtio_spi_del_vq(vdev);
return dev_err_probe(&vdev->dev, ret, "Cannot register
controller\n");
+ }
return 0;
}
+static void virtio_spi_remove(struct virtio_device *vdev)
+{
+ struct spi_controller *ctrl = dev_get_drvdata(&vdev->dev);
+
+ spi_unregister_controller(ctrl);
+
+ virtio_spi_del_vq(vdev);
+}
+
static int virtio_spi_freeze(struct device *dev)
{
struct spi_controller *ctrl = dev_get_drvdata(dev);
@@ -415,6 +418,7 @@ static struct virtio_driver virtio_spi_driver = {
},
.id_table = virtio_spi_id_table,
.probe = virtio_spi_probe,
+ .remove = virtio_spi_remove,
};
module_virtio_driver(virtio_spi_driver);
---
base-commit: fa4ad798f6f681031775266044ba1b0cf3c670bd
change-id: 20261108-spi_virtio_remove-8c285a0d4725
Best regards,
--
Francesco Valla <[email protected]>