From: Simon Glass <sjg@chromium.org>
The rng, net, blk and scsi drivers all use virtio_reset() as their
remove() method.
virtio_reset() only uses the transport's reset() operation, leaving the
virtual queues still allocated (12 KB per virtqueue). Every probe/remove
cycle of a virtio device therefore fails to free its queues.
Add a remove() method to delete the queues before resetting. Update the
four drivers to use it.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
drivers/virtio/virtio-uclass.c | 7 +++++++
drivers/virtio/virtio_blk.c | 2 +-
drivers/virtio/virtio_net.c | 2 +-
drivers/virtio/virtio_rng.c | 2 +-
drivers/virtio/virtio_scsi.c | 2 +-
include/virtio.h | 8 ++++++++
6 files changed, 19 insertions(+), 4 deletions(-)
@@ -105,6 +105,13 @@ int virtio_reset(struct udevice *vdev)
return ops->reset(vdev->parent);
}
+int virtio_remove(struct udevice *vdev)
+{
+ virtio_del_vqs(vdev);
+
+ return virtio_reset(vdev);
+}
+
int virtio_get_features(struct udevice *vdev, u64 *features)
{
struct dm_virtio_ops *ops;
@@ -222,7 +222,7 @@ U_BOOT_DRIVER(virtio_blk) = {
.ops = &virtio_blk_ops,
.bind = virtio_blk_bind,
.probe = virtio_blk_probe,
- .remove = virtio_reset,
+ .remove = virtio_remove,
.priv_auto = sizeof(struct virtio_blk_priv),
.flags = DM_FLAG_ACTIVE_DMA,
};
@@ -233,7 +233,7 @@ U_BOOT_DRIVER(virtio_net) = {
.id = UCLASS_ETH,
.bind = virtio_net_bind,
.probe = virtio_net_probe,
- .remove = virtio_reset,
+ .remove = virtio_remove,
.ops = &virtio_net_ops,
.priv_auto = sizeof(struct virtio_net_priv),
.plat_auto = sizeof(struct eth_pdata),
@@ -89,7 +89,7 @@ U_BOOT_DRIVER(virtio_rng) = {
.id = UCLASS_RNG,
.bind = virtio_rng_bind,
.probe = virtio_rng_probe,
- .remove = virtio_reset,
+ .remove = virtio_remove,
.ops = &virtio_rng_ops,
.priv_auto = sizeof(struct virtio_rng_priv),
.flags = DM_FLAG_ACTIVE_DMA,
@@ -243,7 +243,7 @@ U_BOOT_DRIVER(virtio_scsi) = {
.priv_auto = sizeof(struct virtio_scsi_priv),
.ops = &virtio_scsi_ops,
.probe = virtio_scsi_probe,
- .remove = virtio_reset,
+ .remove = virtio_remove,
.bind = virtio_scsi_bind,
.flags = DM_FLAG_ACTIVE_DMA,
};
@@ -294,6 +294,14 @@ int virtio_set_status(struct udevice *vdev, u8 status);
*/
int virtio_reset(struct udevice *vdev);
+/**
+ * virtio_remove() - remove a virtio device by deleting its vqs and resetting it
+ *
+ * @vdev: the real virtio device
+ * Return: 0 if OK, -ve on error
+ */
+int virtio_remove(struct udevice *vdev);
+
/**
* virtio_get_features() - get the array of feature bits for this device
*