diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:50:03 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:50:03 -0500 |
commit | 6e5aa7efb27aec7e55b6463fa2c8db594c4226fa (patch) | |
tree | 060a955e711ac224136157a5410e88dcdab965af /drivers/lguest | |
parent | b3369c1fb410fddeb38a404316c861395f6d6ae8 (diff) |
virtio: reset function
A reset function solves three problems:
1) It allows us to renegotiate features, eg. if we want to upgrade a
guest driver without rebooting the guest.
2) It gives us a clean way of shutting down virtqueues: after a reset,
we know that the buffers won't be used by the host, and
3) It helps the guest recover from messed-up drivers.
So we remove the ->shutdown hook, and the only way we now remove
feature bits is via reset.
We leave it to the driver to do the reset before it deletes queues:
the balloon driver, for example, needs to chat to the host in its
remove function.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest')
-rw-r--r-- | drivers/lguest/lguest_device.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index ced5b44cebce..84f85e23cca7 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -54,7 +54,7 @@ struct lguest_device { | |||
54 | * | 54 | * |
55 | * The configuration information for a device consists of one or more | 55 | * The configuration information for a device consists of one or more |
56 | * virtqueues, a feature bitmaks, and some configuration bytes. The | 56 | * virtqueues, a feature bitmaks, and some configuration bytes. The |
57 | * configuration bytes don't really matter to us: the Launcher set them up, and | 57 | * configuration bytes don't really matter to us: the Launcher sets them up, and |
58 | * the driver will look at them during setup. | 58 | * the driver will look at them during setup. |
59 | * | 59 | * |
60 | * A convenient routine to return the device's virtqueue config array: | 60 | * A convenient routine to return the device's virtqueue config array: |
@@ -139,9 +139,20 @@ static u8 lg_get_status(struct virtio_device *vdev) | |||
139 | 139 | ||
140 | static void lg_set_status(struct virtio_device *vdev, u8 status) | 140 | static void lg_set_status(struct virtio_device *vdev, u8 status) |
141 | { | 141 | { |
142 | BUG_ON(!status); | ||
142 | to_lgdev(vdev)->desc->status = status; | 143 | to_lgdev(vdev)->desc->status = status; |
143 | } | 144 | } |
144 | 145 | ||
146 | /* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor | ||
147 | * address of the device. The Host will zero the status and all the | ||
148 | * features. */ | ||
149 | static void lg_reset(struct virtio_device *vdev) | ||
150 | { | ||
151 | unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; | ||
152 | |||
153 | hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); | ||
154 | } | ||
155 | |||
145 | /* | 156 | /* |
146 | * Virtqueues | 157 | * Virtqueues |
147 | * | 158 | * |
@@ -279,6 +290,7 @@ static struct virtio_config_ops lguest_config_ops = { | |||
279 | .set = lg_set, | 290 | .set = lg_set, |
280 | .get_status = lg_get_status, | 291 | .get_status = lg_get_status, |
281 | .set_status = lg_set_status, | 292 | .set_status = lg_set_status, |
293 | .reset = lg_reset, | ||
282 | .find_vq = lg_find_vq, | 294 | .find_vq = lg_find_vq, |
283 | .del_vq = lg_del_vq, | 295 | .del_vq = lg_del_vq, |
284 | }; | 296 | }; |