diff options
author | Dexuan Cui | 2019-09-11 23:34:10 +0000 |
---|---|---|
committer | Sasha Levin | 2019-11-21 20:10:44 -0500 |
commit | 1ecf302021040194ae46cceefe33ab75577e356d (patch) | |
tree | aa5a4412c6ea3ae5eea7ed02e87ead4ddbecb6a0 /drivers/video | |
parent | 56fb105859345d65aed08ebbb0f6160c4f0777eb (diff) |
video: hyperv_fb: Add the support of hibernation
This patch depends on the vmbus side change of the definition of
struct hv_driver.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/hyperv_fb.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 2dcb7c58b31e..fe4731f97df7 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -34,6 +34,7 @@ #include <linux/fb.h> #include <linux/pci.h> #include <linux/efi.h> +#include <linux/console.h> #include <linux/hyperv.h> @@ -211,6 +212,7 @@ struct hvfb_par { struct delayed_work dwork; bool update; + bool update_saved; /* The value of 'update' before hibernation */ u32 pseudo_palette[16]; u8 init_buf[MAX_VMBUS_PKT_SIZE]; @@ -878,6 +880,61 @@ static int hvfb_remove(struct hv_device *hdev) return 0; } +static int hvfb_suspend(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + + console_lock(); + + /* 1 means do suspend */ + fb_set_suspend(info, 1); + + cancel_delayed_work_sync(&par->dwork); + + par->update_saved = par->update; + par->update = false; + par->fb_ready = false; + + vmbus_close(hdev->channel); + + console_unlock(); + + return 0; +} + +static int hvfb_resume(struct hv_device *hdev) +{ + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + int ret; + + console_lock(); + + ret = synthvid_connect_vsp(hdev); + if (ret != 0) + goto out; + + ret = synthvid_send_config(hdev); + if (ret != 0) { + vmbus_close(hdev->channel); + goto out; + } + + par->fb_ready = true; + par->update = par->update_saved; + + schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); + + /* 0 means do resume */ + fb_set_suspend(info, 0); + +out: + console_unlock(); + + return ret; +} + static const struct pci_device_id pci_stub_id_table[] = { { @@ -901,6 +958,8 @@ static struct hv_driver hvfb_drv = { .id_table = id_table, .probe = hvfb_probe, .remove = hvfb_remove, + .suspend = hvfb_suspend, + .resume = hvfb_resume, .driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, |