diff options
Diffstat (limited to 'drivers/virtio')
-rw-r--r-- | drivers/virtio/config.c | 1 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 72 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 74 |
3 files changed, 54 insertions, 93 deletions
diff --git a/drivers/virtio/config.c b/drivers/virtio/config.c index 983d482fba40..f70bcd2ff98f 100644 --- a/drivers/virtio/config.c +++ b/drivers/virtio/config.c @@ -9,5 +9,4 @@ #include <linux/virtio.h> #include <linux/virtio_config.h> #include <linux/bug.h> -#include <asm/system.h> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 958e5129c601..c2d05a8279fd 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -28,6 +28,13 @@ #include <linux/slab.h> #include <linux/module.h> +/* + * Balloon device works in 4K page units. So each page is pointed to by + * multiple balloon pages. All memory counters in this driver are in balloon + * page units. + */ +#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) + struct virtio_balloon { struct virtio_device *vdev; @@ -42,8 +49,13 @@ struct virtio_balloon /* Waiting for host to ack the pages we released. */ struct completion acked; - /* The pages we've told the Host we're not using. */ + /* Number of balloon pages we've told the Host we're not using. */ unsigned int num_pages; + /* + * The pages we've told the Host we're not using. + * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE + * to num_pages above. + */ struct list_head pages; /* The array of pfns we tell the Host about. */ @@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page) BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT); /* Convert pfn from Linux page size to balloon page size. */ - return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT); + return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE; +} + +static struct page *balloon_pfn_to_page(u32 pfn) +{ + BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE); + return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE); } static void balloon_ack(struct virtqueue *vq) @@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) wait_for_completion(&vb->acked); } +static void set_page_pfns(u32 pfns[], struct page *page) +{ + unsigned int i; + + /* Set balloon pfns pointing at this page. + * Note that the first pfn points at start of the page. */ + for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++) + pfns[i] = page_to_balloon_pfn(page) + i; +} + static void fill_balloon(struct virtio_balloon *vb, size_t num) { /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); if (!page) { @@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) msleep(200); break; } - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; totalram_pages--; - vb->num_pages++; list_add(&page->lru, &vb->pages); } @@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) { unsigned int i; - for (i = 0; i < num; i++) { - __free_page(pfn_to_page(pfns[i])); + /* Find pfns pointing at start of each page, get pages and free them. */ + for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) { + __free_page(balloon_pfn_to_page(pfns[i])); totalram_pages++; } } @@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) /* We can only do one array worth at a time. */ num = min(num, ARRAY_SIZE(vb->pfns)); - for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) { + for (vb->num_pfns = 0; vb->num_pfns < num; + vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { page = list_first_entry(&vb->pages, struct page, lru); list_del(&page->lru); - vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page); - vb->num_pages--; + set_page_pfns(vb->pfns + vb->num_pfns, page); + vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; } /* @@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev) static inline s64 towards_target(struct virtio_balloon *vb) { - u32 v; + __le32 v; + s64 target; + vb->vdev->config->get(vb->vdev, offsetof(struct virtio_balloon_config, num_pages), &v, sizeof(v)); - return (s64)v - vb->num_pages; + target = le32_to_cpu(v); + return target - vb->num_pages; } static void update_balloon_size(struct virtio_balloon *vb) @@ -398,21 +432,8 @@ static int restore_common(struct virtio_device *vdev) return 0; } -static int virtballoon_thaw(struct virtio_device *vdev) -{ - return restore_common(vdev); -} - static int virtballoon_restore(struct virtio_device *vdev) { - struct virtio_balloon *vb = vdev->priv; - - /* - * If a request wasn't complete at the time of freezing, this - * could have been set. - */ - vb->need_stats_update = 0; - return restore_common(vdev); } #endif @@ -434,7 +455,6 @@ static struct virtio_driver virtio_balloon_driver = { #ifdef CONFIG_PM .freeze = virtballoon_freeze, .restore = virtballoon_restore, - .thaw = virtballoon_thaw, #endif }; diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 635e1efb3792..2e03d416b9af 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -720,24 +720,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) } #ifdef CONFIG_PM -static int virtio_pci_suspend(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - - pci_save_state(pci_dev); - pci_set_power_state(pci_dev, PCI_D3hot); - return 0; -} - -static int virtio_pci_resume(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - - pci_restore_state(pci_dev); - pci_set_power_state(pci_dev, PCI_D0); - return 0; -} - static int virtio_pci_freeze(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -758,59 +740,24 @@ static int virtio_pci_freeze(struct device *dev) return ret; } -static int restore_common(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - int ret; - - ret = pci_enable_device(pci_dev); - if (ret) - return ret; - pci_set_master(pci_dev); - vp_finalize_features(&vp_dev->vdev); - - return ret; -} - -static int virtio_pci_thaw(struct device *dev) +static int virtio_pci_restore(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); struct virtio_driver *drv; int ret; - ret = restore_common(dev); - if (ret) - return ret; - drv = container_of(vp_dev->vdev.dev.driver, struct virtio_driver, driver); - if (drv && drv->thaw) - ret = drv->thaw(&vp_dev->vdev); - else if (drv && drv->restore) - ret = drv->restore(&vp_dev->vdev); - - /* Finally, tell the device we're all set */ - if (!ret) - vp_set_status(&vp_dev->vdev, vp_dev->saved_status); - - return ret; -} - -static int virtio_pci_restore(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct virtio_driver *drv; - int ret; + ret = pci_enable_device(pci_dev); + if (ret) + return ret; - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); + pci_set_master(pci_dev); + vp_finalize_features(&vp_dev->vdev); - ret = restore_common(dev); - if (!ret && drv && drv->restore) + if (drv && drv->restore) ret = drv->restore(&vp_dev->vdev); /* Finally, tell the device we're all set */ @@ -821,12 +768,7 @@ static int virtio_pci_restore(struct device *dev) } static const struct dev_pm_ops virtio_pci_pm_ops = { - .suspend = virtio_pci_suspend, - .resume = virtio_pci_resume, - .freeze = virtio_pci_freeze, - .thaw = virtio_pci_thaw, - .restore = virtio_pci_restore, - .poweroff = virtio_pci_suspend, + SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) }; #endif |