From: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> The mem hot-remove operation and balloon down will be added or moved into work context. Add a common work to handle opeations of mem hot-add/remove and balloon up/down. Signed-off-by: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> --- drivers/hv/hv_balloon.c | 86 ++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index b155d0052981..bdb6791e6de1 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -447,15 +447,20 @@ struct hv_hotadd_gap { unsigned long end_pfn; }; -struct balloon_state { - __u32 num_pages; - struct work_struct wrk; +union dm_msg_info { + struct { + __u32 num_pages; + } balloon_state; + struct { + union dm_mem_page_range ha_page_range; + union dm_mem_page_range ha_region_range; + } hot_add; }; -struct hot_add_wrk { - union dm_mem_page_range ha_page_range; - union dm_mem_page_range ha_region_range; +struct dm_msg_wrk { + enum dm_message_type msg_type; struct work_struct wrk; + union dm_msg_info dm_msg; }; static bool allow_hibernation; @@ -514,14 +519,9 @@ struct hv_dynmem_device { unsigned int num_pages_added; /* - * State to manage the ballooning (up) operation. + * State to manage the ballooning (up) and "hot-add" operation. */ - struct balloon_state balloon_wrk; - - /* - * State to execute the "hot-add" operation. - */ - struct hot_add_wrk ha_wrk; + struct dm_msg_wrk dm_wrk; /* * This state tracks if the host has specified a hot-add @@ -982,7 +982,7 @@ static unsigned long process_hot_add(unsigned long pg_start, #endif -static void hot_add_req(struct work_struct *dummy) +static void hot_add_req(union dm_msg_info *msg_info) { struct dm_hot_add_response resp; #ifdef CONFIG_MEMORY_HOTPLUG @@ -996,11 +996,11 @@ static void hot_add_req(struct work_struct *dummy) resp.hdr.size = sizeof(struct dm_hot_add_response); #ifdef CONFIG_MEMORY_HOTPLUG - pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; - pfn_cnt = dm->ha_wrk.ha_page_range.finfo.page_cnt; + pg_start = msg_info->hot_add.ha_page_range.finfo.start_page; + pfn_cnt = msg_info->hot_add.ha_page_range.finfo.page_cnt; - rg_start = dm->ha_wrk.ha_region_range.finfo.start_page; - rg_sz = dm->ha_wrk.ha_region_range.finfo.page_cnt; + rg_start = msg_info->hot_add.ha_region_range.finfo.start_page; + rg_sz = msg_info->hot_add.ha_region_range.finfo.page_cnt; if ((rg_start == 0) && (!dm->host_specified_ha_region)) { unsigned long region_size; @@ -1261,9 +1261,9 @@ static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm, return num_pages; } -static void balloon_up(struct work_struct *dummy) +static void balloon_up(union dm_msg_info *msg_info) { - unsigned int num_pages = dm_device.balloon_wrk.num_pages; + unsigned int num_pages = msg_info->balloon_state.num_pages; unsigned int num_ballooned = 0; struct dm_balloon_response *bl_resp; int alloc_unit; @@ -1313,7 +1313,7 @@ static void balloon_up(struct work_struct *dummy) if (num_ballooned == 0 || num_ballooned == num_pages) { pr_debug("Ballooned %u out of %u requested pages.\n", - num_pages, dm_device.balloon_wrk.num_pages); + num_pages, msg_info->balloon_state.num_pages); bl_resp->more_pages = 0; done = true; @@ -1355,6 +1355,22 @@ static void balloon_up(struct work_struct *dummy) } +static void dm_msg_work(struct work_struct *dummy) +{ + union dm_msg_info *msg_info = &dm_device.dm_wrk.dm_msg; + + switch (dm_device.dm_wrk.msg_type) { + case DM_BALLOON_REQUEST: + balloon_up(msg_info); + break; + case DM_MEM_HOT_ADD_REQUEST: + hot_add_req(msg_info); + break; + default: + return; + } +} + static void balloon_down(struct hv_dynmem_device *dm, struct dm_unballoon_request *req) { @@ -1490,6 +1506,8 @@ static void balloon_onchannelcallback(void *context) struct hv_dynmem_device *dm = hv_get_drvdata(dev); struct dm_balloon *bal_msg; struct dm_hot_add *ha_msg; + struct dm_msg_wrk *dm_wrk = &dm_device.dm_wrk; + union dm_msg_info *msg_info = &dm_wrk->dm_msg; union dm_mem_page_range *ha_pg_range; union dm_mem_page_range *ha_region; @@ -1522,8 +1540,9 @@ static void balloon_onchannelcallback(void *context) pr_warn("Currently ballooning\n"); bal_msg = (struct dm_balloon *)recv_buffer; dm->state = DM_BALLOON_UP; - dm_device.balloon_wrk.num_pages = bal_msg->num_pages; - schedule_work(&dm_device.balloon_wrk.wrk); + msg_info->balloon_state.num_pages = bal_msg->num_pages; + dm_wrk->msg_type = DM_BALLOON_REQUEST; + schedule_work(&dm_wrk->wrk); break; case DM_UNBALLOON_REQUEST: @@ -1549,8 +1568,9 @@ static void balloon_onchannelcallback(void *context) */ dm->host_specified_ha_region = false; ha_pg_range = &ha_msg->range; - dm->ha_wrk.ha_page_range = *ha_pg_range; - dm->ha_wrk.ha_region_range.page_range = 0; + msg_info->hot_add.ha_page_range = *ha_pg_range; + msg_info->hot_add.ha_region_range.page_range + = 0; } else { /* * Host is specifying that we first hot-add @@ -1560,10 +1580,11 @@ static void balloon_onchannelcallback(void *context) dm->host_specified_ha_region = true; ha_pg_range = &ha_msg->range; ha_region = &ha_pg_range[1]; - dm->ha_wrk.ha_page_range = *ha_pg_range; - dm->ha_wrk.ha_region_range = *ha_region; + msg_info->hot_add.ha_page_range = *ha_pg_range; + msg_info->hot_add.ha_region_range = *ha_region; } - schedule_work(&dm_device.ha_wrk.wrk); + dm_wrk->msg_type = DM_MEM_HOT_ADD_REQUEST; + schedule_work(&dm_wrk->wrk); break; case DM_INFO_MESSAGE: @@ -1707,8 +1728,7 @@ static int balloon_probe(struct hv_device *dev, init_completion(&dm_device.config_event); INIT_LIST_HEAD(&dm_device.ha_region_list); spin_lock_init(&dm_device.ha_lock); - INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up); - INIT_WORK(&dm_device.ha_wrk.wrk, hot_add_req); + INIT_WORK(&dm_device.dm_wrk.wrk, dm_msg_work); dm_device.host_specified_ha_region = false; #ifdef CONFIG_MEMORY_HOTPLUG @@ -1754,8 +1774,7 @@ static int balloon_remove(struct hv_device *dev) if (dm->num_pages_ballooned != 0) pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); - cancel_work_sync(&dm->balloon_wrk.wrk); - cancel_work_sync(&dm->ha_wrk.wrk); + cancel_work_sync(&dm->dm_wrk.wrk); kthread_stop(dm->thread); vmbus_close(dev->channel); @@ -1783,8 +1802,7 @@ static int balloon_suspend(struct hv_device *hv_dev) tasklet_disable(&hv_dev->channel->callback_event); - cancel_work_sync(&dm->balloon_wrk.wrk); - cancel_work_sync(&dm->ha_wrk.wrk); + cancel_work_sync(&dm->dm_wrk.wrk); if (dm->thread) { kthread_stop(dm->thread); -- 2.14.5