[PATCH v2 09/12] virtio: locate the device memory buffer after feature negotiation

Alexander Graf <[email protected]>
Newsgroups dev.linux.lists.virtualization,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
In preparation to support VIRTIO_F_DMB, locate a device's Device Memory
Buffer once feature negotiation is complete. The shared memory id that
locates the region may only be read after the device has confirmed
FEATURES_OK, and finalize_features() runs before that.

virtio_features_ok() is the one place in the core that has just read
FEATURES_OK back, so locate the region from there, and release it from
virtio_dev_remove() and from the error paths of probe and restore.
Restore and reset completion reach it too, where virtio_dmb_init() keeps
the state of a device reporting the region it had, rebuilds it for a
device reporting a different one, and refuses a device that moves its
region while its driver has virtqueues.

Suspend and reset need no handling of their own. Neither
virtio_device_freeze() nor virtio_reset_device() deletes a virtqueue,
and a live virtqueue holds addresses inside the region, so we keep it
across both.

Link: https://lore.kernel.org/virtio-comment/[email protected]/
Assisted-by: Kiro:claude-opus-5 checkpatch sparse
Signed-off-by: Alexander Graf <[email protected]>
---
 drivers/virtio/virtio.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 299fa83be1d5..6f112593566c 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -8,6 +8,8 @@
 #include <linux/of.h>
 #include <uapi/linux/virtio_ids.h>
 
+#include "virtio_dmb.h"
+
 /* Unique numbering for virtio devices. */
 static DEFINE_IDA(virtio_index_ida);
 
@@ -231,7 +233,14 @@ static int virtio_features_ok(struct virtio_device *dev)
 			status);
 		return -ENODEV;
 	}
-	return 0;
+
+	/*
+	 * Negotiation is complete, so a Device Memory Buffer may now be
+	 * located.  Reached from probe, from resume and from reset
+	 * completion, all of which have to end with the state matching what
+	 * the device reports now.
+	 */
+	return virtio_dmb_init(dev);
 }
 
 /**
@@ -361,6 +370,7 @@ static int virtio_dev_probe(struct device *_d)
 
 err:
 	virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
+	virtio_dmb_destroy(dev);
 	return err;
 
 }
@@ -377,6 +387,8 @@ static void virtio_dev_remove(struct device *_d)
 	/* Driver should have reset device. */
 	WARN_ON_ONCE(dev->config->get_status(dev));
 
+	virtio_dmb_destroy(dev);
+
 	/* Acknowledge the device's existence again. */
 	virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
 
@@ -650,6 +662,7 @@ static int virtio_device_restore_priv(struct virtio_device *dev, bool restore)
 
 err:
 	virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
+	virtio_dmb_destroy(dev);
 	return ret;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.