summary refs log tree commit diff
path: root/tools/lguest
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2015-02-13 17:13:40 +1030
committerRusty Russell <rusty@rustcorp.com.au>2015-02-13 17:15:45 +1030
commitd2dbdac336e8ea1296fd08c4eb8a28daacec1817 (patch)
treecafaba8f442a59c4fde6bd25a551c711a8cbe785 /tools/lguest
parenta2e199915725e666772dd077dbffbef154e58096 (diff)
downloadlinux-d2dbdac336e8ea1296fd08c4eb8a28daacec1817.tar.gz
tools/lguest: handle device reset correctly in example launcher.
The example launcher doesn't reset the queue_enable like the spec says
we have to.  Plus, we should reset the size in case they negotiated
a different (smaller) one.

This is easy to test by unloading and reloading a virtio module.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'tools/lguest')
-rw-r--r--tools/lguest/lguest.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index 5d104321f70f..60cabafdf615 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -1037,6 +1037,12 @@ static void kill_launcher(int signal)
 	kill(0, SIGTERM);
 }
 
+static void reset_vq_pci_config(struct virtqueue *vq)
+{
+	vq->pci_config.queue_size = VIRTQUEUE_NUM;
+	vq->pci_config.queue_enable = 0;
+}
+
 static void reset_device(struct device *dev)
 {
 	struct virtqueue *vq;
@@ -1049,8 +1055,19 @@ static void reset_device(struct device *dev)
 	/* We're going to be explicitly killing threads, so ignore them. */
 	signal(SIGCHLD, SIG_IGN);
 
+	/*
+	 * 4.1.4.3.1:
+	 *
+	 *   The device MUST present a 0 in queue_enable on reset. 
+	 *
+	 * This means we set it here, and reset the saved ones in every vq.
+	 */
+	dev->mmio->cfg.queue_enable = 0;
+
 	/* Get rid of the virtqueue threads */
 	for (vq = dev->vq; vq; vq = vq->next) {
+		vq->last_avail_idx = 0;
+		reset_vq_pci_config(vq);
 		if (vq->thread != (pid_t)-1) {
 			kill(vq->thread, SIGTERM);
 			waitpid(vq->thread, NULL, 0);
@@ -1952,8 +1969,7 @@ static void add_pci_virtqueue(struct device *dev,
 	vq->thread = (pid_t)-1;
 
 	/* Initialize the configuration. */
-	vq->pci_config.queue_size = VIRTQUEUE_NUM;
-	vq->pci_config.queue_enable = 0;
+	reset_vq_pci_config(vq);
 	vq->pci_config.queue_notify_off = 0;
 
 	/* Add one to the number of queues */