diff options
Diffstat (limited to 'drivers/virtio/virtio_balloon.c')
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 108 |
1 files changed, 84 insertions, 24 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 94fd738a7741..95aeedf198f8 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Virtio balloon implementation, inspired by Dor Loar and Marcelo | 1 | /* |
2 | * Virtio balloon implementation, inspired by Dor Laor and Marcelo | ||
2 | * Tosatti's implementations. | 3 | * Tosatti's implementations. |
3 | * | 4 | * |
4 | * Copyright 2008 Rusty Russell IBM Corporation | 5 | * Copyright 2008 Rusty Russell IBM Corporation |
@@ -17,7 +18,7 @@ | |||
17 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ | 20 | */ |
20 | //#define DEBUG | 21 | |
21 | #include <linux/virtio.h> | 22 | #include <linux/virtio.h> |
22 | #include <linux/virtio_balloon.h> | 23 | #include <linux/virtio_balloon.h> |
23 | #include <linux/swap.h> | 24 | #include <linux/swap.h> |
@@ -87,7 +88,7 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) | |||
87 | init_completion(&vb->acked); | 88 | init_completion(&vb->acked); |
88 | 89 | ||
89 | /* We should always be able to add one buffer to an empty queue. */ | 90 | /* We should always be able to add one buffer to an empty queue. */ |
90 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0) | 91 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0) |
91 | BUG(); | 92 | BUG(); |
92 | virtqueue_kick(vq); | 93 | virtqueue_kick(vq); |
93 | 94 | ||
@@ -149,7 +150,6 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) | |||
149 | vb->num_pages--; | 150 | vb->num_pages--; |
150 | } | 151 | } |
151 | 152 | ||
152 | |||
153 | /* | 153 | /* |
154 | * Note that if | 154 | * Note that if |
155 | * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); | 155 | * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); |
@@ -220,7 +220,7 @@ static void stats_handle_request(struct virtio_balloon *vb) | |||
220 | 220 | ||
221 | vq = vb->stats_vq; | 221 | vq = vb->stats_vq; |
222 | sg_init_one(&sg, vb->stats, sizeof(vb->stats)); | 222 | sg_init_one(&sg, vb->stats, sizeof(vb->stats)); |
223 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0) | 223 | if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0) |
224 | BUG(); | 224 | BUG(); |
225 | virtqueue_kick(vq); | 225 | virtqueue_kick(vq); |
226 | } | 226 | } |
@@ -275,32 +275,21 @@ static int balloon(void *_vballoon) | |||
275 | return 0; | 275 | return 0; |
276 | } | 276 | } |
277 | 277 | ||
278 | static int virtballoon_probe(struct virtio_device *vdev) | 278 | static int init_vqs(struct virtio_balloon *vb) |
279 | { | 279 | { |
280 | struct virtio_balloon *vb; | ||
281 | struct virtqueue *vqs[3]; | 280 | struct virtqueue *vqs[3]; |
282 | vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request }; | 281 | vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request }; |
283 | const char *names[] = { "inflate", "deflate", "stats" }; | 282 | const char *names[] = { "inflate", "deflate", "stats" }; |
284 | int err, nvqs; | 283 | int err, nvqs; |
285 | 284 | ||
286 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); | 285 | /* |
287 | if (!vb) { | 286 | * We expect two virtqueues: inflate and deflate, and |
288 | err = -ENOMEM; | 287 | * optionally stat. |
289 | goto out; | 288 | */ |
290 | } | ||
291 | |||
292 | INIT_LIST_HEAD(&vb->pages); | ||
293 | vb->num_pages = 0; | ||
294 | init_waitqueue_head(&vb->config_change); | ||
295 | vb->vdev = vdev; | ||
296 | vb->need_stats_update = 0; | ||
297 | |||
298 | /* We expect two virtqueues: inflate and deflate, | ||
299 | * and optionally stat. */ | ||
300 | nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; | 289 | nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2; |
301 | err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names); | 290 | err = vb->vdev->config->find_vqs(vb->vdev, nvqs, vqs, callbacks, names); |
302 | if (err) | 291 | if (err) |
303 | goto out_free_vb; | 292 | return err; |
304 | 293 | ||
305 | vb->inflate_vq = vqs[0]; | 294 | vb->inflate_vq = vqs[0]; |
306 | vb->deflate_vq = vqs[1]; | 295 | vb->deflate_vq = vqs[1]; |
@@ -313,10 +302,34 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
313 | * use it to signal us later. | 302 | * use it to signal us later. |
314 | */ | 303 | */ |
315 | sg_init_one(&sg, vb->stats, sizeof vb->stats); | 304 | sg_init_one(&sg, vb->stats, sizeof vb->stats); |
316 | if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb) < 0) | 305 | if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb, GFP_KERNEL) |
306 | < 0) | ||
317 | BUG(); | 307 | BUG(); |
318 | virtqueue_kick(vb->stats_vq); | 308 | virtqueue_kick(vb->stats_vq); |
319 | } | 309 | } |
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int virtballoon_probe(struct virtio_device *vdev) | ||
314 | { | ||
315 | struct virtio_balloon *vb; | ||
316 | int err; | ||
317 | |||
318 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); | ||
319 | if (!vb) { | ||
320 | err = -ENOMEM; | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | INIT_LIST_HEAD(&vb->pages); | ||
325 | vb->num_pages = 0; | ||
326 | init_waitqueue_head(&vb->config_change); | ||
327 | vb->vdev = vdev; | ||
328 | vb->need_stats_update = 0; | ||
329 | |||
330 | err = init_vqs(vb); | ||
331 | if (err) | ||
332 | goto out_free_vb; | ||
320 | 333 | ||
321 | vb->thread = kthread_run(balloon, vb, "vballoon"); | 334 | vb->thread = kthread_run(balloon, vb, "vballoon"); |
322 | if (IS_ERR(vb->thread)) { | 335 | if (IS_ERR(vb->thread)) { |
@@ -351,6 +364,48 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev) | |||
351 | kfree(vb); | 364 | kfree(vb); |
352 | } | 365 | } |
353 | 366 | ||
367 | #ifdef CONFIG_PM | ||
368 | static int virtballoon_freeze(struct virtio_device *vdev) | ||
369 | { | ||
370 | /* | ||
371 | * The kthread is already frozen by the PM core before this | ||
372 | * function is called. | ||
373 | */ | ||
374 | |||
375 | /* Ensure we don't get any more requests from the host */ | ||
376 | vdev->config->reset(vdev); | ||
377 | vdev->config->del_vqs(vdev); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int virtballoon_thaw(struct virtio_device *vdev) | ||
382 | { | ||
383 | return init_vqs(vdev->priv); | ||
384 | } | ||
385 | |||
386 | static int virtballoon_restore(struct virtio_device *vdev) | ||
387 | { | ||
388 | struct virtio_balloon *vb = vdev->priv; | ||
389 | struct page *page, *page2; | ||
390 | |||
391 | /* We're starting from a clean slate */ | ||
392 | vb->num_pages = 0; | ||
393 | |||
394 | /* | ||
395 | * If a request wasn't complete at the time of freezing, this | ||
396 | * could have been set. | ||
397 | */ | ||
398 | vb->need_stats_update = 0; | ||
399 | |||
400 | /* We don't have these pages in the balloon anymore! */ | ||
401 | list_for_each_entry_safe(page, page2, &vb->pages, lru) { | ||
402 | list_del(&page->lru); | ||
403 | totalram_pages++; | ||
404 | } | ||
405 | return init_vqs(vdev->priv); | ||
406 | } | ||
407 | #endif | ||
408 | |||
354 | static unsigned int features[] = { | 409 | static unsigned int features[] = { |
355 | VIRTIO_BALLOON_F_MUST_TELL_HOST, | 410 | VIRTIO_BALLOON_F_MUST_TELL_HOST, |
356 | VIRTIO_BALLOON_F_STATS_VQ, | 411 | VIRTIO_BALLOON_F_STATS_VQ, |
@@ -365,6 +420,11 @@ static struct virtio_driver virtio_balloon_driver = { | |||
365 | .probe = virtballoon_probe, | 420 | .probe = virtballoon_probe, |
366 | .remove = __devexit_p(virtballoon_remove), | 421 | .remove = __devexit_p(virtballoon_remove), |
367 | .config_changed = virtballoon_changed, | 422 | .config_changed = virtballoon_changed, |
423 | #ifdef CONFIG_PM | ||
424 | .freeze = virtballoon_freeze, | ||
425 | .restore = virtballoon_restore, | ||
426 | .thaw = virtballoon_thaw, | ||
427 | #endif | ||
368 | }; | 428 | }; |
369 | 429 | ||
370 | static int __init init(void) | 430 | static int __init init(void) |