From 38e25c0f7e9e390a0eacd48e96020117268388f3 Mon Sep 17 00:00:00 2001
From: Long Li <longli@microsoft.com>
Date: Tue, 11 Nov 2014 17:10:20 +0000
Subject: [PATCH] Move unballoon to work queue

---
 drivers/hv/hv_balloon.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 5e90c5d..d5b11d5 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -509,6 +509,9 @@ struct hv_dynmem_device {
 	 */
 	struct balloon_state balloon_wrk;
 
+	struct dm_unballoon_request *unballoon_req;
+	struct balloon_state unballoon_wrk;
+
 	/*
 	 * State to execute the "hot-add" operation.
 	 */
@@ -1157,16 +1160,16 @@ static void balloon_up(struct work_struct *dummy)
 
 }
 
-static void balloon_down(struct hv_dynmem_device *dm,
-			struct dm_unballoon_request *req)
+static void balloon_down(struct work_struct *dummy)
 {
+	struct dm_unballoon_request *req = dm_device.unballoon_req;
 	union dm_mem_page_range *range_array = req->range_array;
 	int range_count = req->range_count;
 	struct dm_unballoon_response resp;
 	int i;
 
 	for (i = 0; i < range_count; i++) {
-		free_balloon_pages(dm, &range_array[i]);
+		free_balloon_pages(&dm_device, &range_array[i]);
 		post_status(&dm_device);
 	}
 
@@ -1183,7 +1186,7 @@ static void balloon_down(struct hv_dynmem_device *dm,
 				(unsigned long)NULL,
 				VM_PKT_DATA_INBAND, 0);
 
-	dm->state = DM_INITIALIZED;
+	dm_device.state = DM_INITIALIZED;
 }
 
 static void balloon_onchannelcallback(void *context);
@@ -1311,8 +1314,8 @@ static void balloon_onchannelcallback(void *context)
 
 		case DM_UNBALLOON_REQUEST:
 			dm->state = DM_BALLOON_DOWN;
-			balloon_down(dm,
-				 (struct dm_unballoon_request *)recv_buffer);
+			dm->unballoon_req = (struct dm_unballoon_request *)recv_buffer;
+			schedule_work(&dm_device.unballoon_wrk.wrk);
 			break;
 
 		case DM_MEM_HOT_ADD_REQUEST:
@@ -1385,6 +1388,7 @@ static int balloon_probe(struct hv_device *dev,
 	init_completion(&dm_device.config_event);
 	INIT_LIST_HEAD(&dm_device.ha_region_list);
 	INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up);
+	INIT_WORK(&dm_device.unballoon_wrk.wrk, balloon_down);
 	INIT_WORK(&dm_device.ha_wrk.wrk, hot_add_req);
 	dm_device.host_specified_ha_region = false;
 
@@ -1508,6 +1512,7 @@ static int balloon_remove(struct hv_device *dev)
 		pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
 
 	cancel_work_sync(&dm->balloon_wrk.wrk);
+	cancel_work_sync(&dm->unballoon_wrk.wrk);
 	cancel_work_sync(&dm->ha_wrk.wrk);
 
 	vmbus_close(dev->channel);
-- 
2.1.0

