diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-08 13:39:59 +0200 | 
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-08 13:39:59 +0200 | 
| commit | 5e13a0c5ec05d382b488a691dfb8af015b1dea1e (patch) | |
| tree | 7a06dfa1f7661f8908193f2437b32452520221d3 /drivers/virtio/virtio_balloon.c | |
| parent | b615b57a124a4af7b68196bc2fb8acc236041fa2 (diff) | |
| parent | 4f256e8aa3eda15c11c3cec3ec5336e1fc579cbd (diff) | |
| download | olio-linux-3.10-5e13a0c5ec05d382b488a691dfb8af015b1dea1e.tar.xz olio-linux-3.10-5e13a0c5ec05d382b488a691dfb8af015b1dea1e.zip  | |
Merge remote-tracking branch 'airlied/drm-core-next' into drm-intel-next-queued
Backmerge of drm-next to resolve a few ugly conflicts and to get a few
fixes from 3.4-rc6 (which drm-next has already merged). Note that this
merge also restricts the stencil cache lra evict policy workaround to
snb (as it should) - I had to frob the code anyway because the
CM0_MASK_SHIFT define died in the masked bit cleanups.
We need the backmerge to get Paulo Zanoni's infoframe regression fix
for gm45 - further bugfixes from him touch the same area and would
needlessly conflict.
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/virtio/virtio_balloon.c')
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 58 | 
1 files changed, 46 insertions, 12 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 05f0a80818a..c2d05a8279f 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)  |