aboutsummaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorDexuan Cui2019-09-11 23:34:10 +0000
committerSasha Levin2019-11-21 20:10:44 -0500
commit1ecf302021040194ae46cceefe33ab75577e356d (patch)
treeaa5a4412c6ea3ae5eea7ed02e87ead4ddbecb6a0 /drivers/video
parent56fb105859345d65aed08ebbb0f6160c4f0777eb (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.c59
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,
},