hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/video/fbdev/hyperv_fb.c
....@@ -1,18 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012, Microsoft Corporation.
34 *
45 * Author:
56 * Haiyang Zhang <haiyangz@microsoft.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify it
8
- * under the terms of the GNU General Public License version 2 as published
9
- * by the Free Software Foundation.
10
- *
11
- * This program is distributed in the hope that it will be useful, but
12
- * WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14
- * NON INFRINGEMENT. See the GNU General Public License for more
15
- * details.
167 */
178
189 /*
....@@ -32,17 +23,37 @@
3223 *
3324 * Portrait orientation is also supported:
3425 * For example: video=hyperv_fb:864x1152
26
+ *
27
+ * When a Windows 10 RS5+ host is used, the virtual machine screen
28
+ * resolution is obtained from the host. The "video=hyperv_fb" option is
29
+ * not needed, but still can be used to overwrite what the host specifies.
30
+ * The VM resolution on the host could be set by executing the powershell
31
+ * "set-vmvideo" command. For example
32
+ * set-vmvideo -vmname name -horizontalresolution:1920 \
33
+ * -verticalresolution:1200 -resolutiontype single
34
+ *
35
+ * Gen 1 VMs also support direct using VM's physical memory for framebuffer.
36
+ * It could improve the efficiency and performance for framebuffer and VM.
37
+ * This requires to allocate contiguous physical memory from Linux kernel's
38
+ * CMA memory allocator. To enable this, supply a kernel parameter to give
39
+ * enough memory space to CMA allocator for framebuffer. For example:
40
+ * cma=130m
41
+ * This gives 130MB memory to CMA allocator that can be allocated to
42
+ * framebuffer. For reference, 8K resolution (7680x4320) takes about
43
+ * 127MB memory.
3544 */
3645
3746 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3847
3948 #include <linux/module.h>
4049 #include <linux/kernel.h>
50
+#include <linux/vmalloc.h>
4151 #include <linux/init.h>
4252 #include <linux/completion.h>
4353 #include <linux/fb.h>
4454 #include <linux/pci.h>
4555 #include <linux/efi.h>
56
+#include <linux/console.h>
4657
4758 #include <linux/hyperv.h>
4859
....@@ -53,6 +64,10 @@
5364 #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
5465 #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
5566 #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
67
+#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5)
68
+
69
+#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff)
70
+#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16)
5671
5772 #define SYNTHVID_DEPTH_WIN7 16
5873 #define SYNTHVID_DEPTH_WIN8 32
....@@ -91,15 +106,24 @@
91106 SYNTHVID_POINTER_SHAPE = 8,
92107 SYNTHVID_FEATURE_CHANGE = 9,
93108 SYNTHVID_DIRT = 10,
109
+ SYNTHVID_RESOLUTION_REQUEST = 13,
110
+ SYNTHVID_RESOLUTION_RESPONSE = 14,
94111
95
- SYNTHVID_MAX = 11
112
+ SYNTHVID_MAX = 15
96113 };
114
+
115
+#define SYNTHVID_EDID_BLOCK_SIZE 128
116
+#define SYNTHVID_MAX_RESOLUTION_COUNT 64
117
+
118
+struct hvd_screen_info {
119
+ u16 width;
120
+ u16 height;
121
+} __packed;
97122
98123 struct synthvid_msg_hdr {
99124 u32 type;
100125 u32 size; /* size of this header + payload after this field*/
101126 } __packed;
102
-
103127
104128 struct synthvid_version_req {
105129 u32 version;
....@@ -109,6 +133,19 @@
109133 u32 version;
110134 u8 is_accepted;
111135 u8 max_video_outputs;
136
+} __packed;
137
+
138
+struct synthvid_supported_resolution_req {
139
+ u8 maximum_resolution_count;
140
+} __packed;
141
+
142
+struct synthvid_supported_resolution_resp {
143
+ u8 edid_block[SYNTHVID_EDID_BLOCK_SIZE];
144
+ u8 resolution_count;
145
+ u8 default_resolution_index;
146
+ u8 is_standard;
147
+ struct hvd_screen_info
148
+ supported_resolution[SYNTHVID_MAX_RESOLUTION_COUNT];
112149 } __packed;
113150
114151 struct synthvid_vram_location {
....@@ -196,9 +233,10 @@
196233 struct synthvid_pointer_shape ptr_shape;
197234 struct synthvid_feature_change feature_chg;
198235 struct synthvid_dirt dirt;
236
+ struct synthvid_supported_resolution_req resolution_req;
237
+ struct synthvid_supported_resolution_resp resolution_resp;
199238 };
200239 } __packed;
201
-
202240
203241
204242 /* FB driver definitions and structures */
....@@ -210,6 +248,7 @@
210248 #define RING_BUFSIZE (256 * 1024)
211249 #define VSP_TIMEOUT (10 * HZ)
212250 #define HVFB_UPDATE_DELAY (HZ / 20)
251
+#define HVFB_ONDEMAND_THROTTLE (HZ / 20)
213252
214253 struct hvfb_par {
215254 struct fb_info *info;
....@@ -220,6 +259,7 @@
220259
221260 struct delayed_work dwork;
222261 bool update;
262
+ bool update_saved; /* The value of 'update' before hibernation */
223263
224264 u32 pseudo_palette[16];
225265 u8 init_buf[MAX_VMBUS_PKT_SIZE];
....@@ -228,13 +268,27 @@
228268 /* If true, the VSC notifies the VSP on every framebuffer change */
229269 bool synchronous_fb;
230270
271
+ /* If true, need to copy from deferred IO mem to framebuffer mem */
272
+ bool need_docopy;
273
+
231274 struct notifier_block hvfb_panic_nb;
275
+
276
+ /* Memory for deferred IO and frame buffer itself */
277
+ unsigned char *dio_vp;
278
+ unsigned char *mmio_vp;
279
+ phys_addr_t mmio_pp;
280
+
281
+ /* Dirty rectangle, protected by delayed_refresh_lock */
282
+ int x1, y1, x2, y2;
283
+ bool delayed_refresh;
284
+ spinlock_t delayed_refresh_lock;
232285 };
233286
234287 static uint screen_width = HVFB_WIDTH;
235288 static uint screen_height = HVFB_HEIGHT;
236289 static uint screen_depth;
237290 static uint screen_fb_size;
291
+static uint dio_fb_size; /* FB size for deferred IO */
238292
239293 /* Send message to Hyper-V host */
240294 static inline int synthvid_send(struct hv_device *hdev,
....@@ -321,28 +375,88 @@
321375 }
322376
323377 /* Send updated screen area (dirty rectangle) location to host */
324
-static int synthvid_update(struct fb_info *info)
378
+static int
379
+synthvid_update(struct fb_info *info, int x1, int y1, int x2, int y2)
325380 {
326381 struct hv_device *hdev = device_to_hv_device(info->device);
327382 struct synthvid_msg msg;
328383
329384 memset(&msg, 0, sizeof(struct synthvid_msg));
385
+ if (x2 == INT_MAX)
386
+ x2 = info->var.xres;
387
+ if (y2 == INT_MAX)
388
+ y2 = info->var.yres;
330389
331390 msg.vid_hdr.type = SYNTHVID_DIRT;
332391 msg.vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
333392 sizeof(struct synthvid_dirt);
334393 msg.dirt.video_output = 0;
335394 msg.dirt.dirt_count = 1;
336
- msg.dirt.rect[0].x1 = 0;
337
- msg.dirt.rect[0].y1 = 0;
338
- msg.dirt.rect[0].x2 = info->var.xres;
339
- msg.dirt.rect[0].y2 = info->var.yres;
395
+ msg.dirt.rect[0].x1 = (x1 > x2) ? 0 : x1;
396
+ msg.dirt.rect[0].y1 = (y1 > y2) ? 0 : y1;
397
+ msg.dirt.rect[0].x2 =
398
+ (x2 < x1 || x2 > info->var.xres) ? info->var.xres : x2;
399
+ msg.dirt.rect[0].y2 =
400
+ (y2 < y1 || y2 > info->var.yres) ? info->var.yres : y2;
340401
341402 synthvid_send(hdev, &msg);
342403
343404 return 0;
344405 }
345406
407
+static void hvfb_docopy(struct hvfb_par *par,
408
+ unsigned long offset,
409
+ unsigned long size)
410
+{
411
+ if (!par || !par->mmio_vp || !par->dio_vp || !par->fb_ready ||
412
+ size == 0 || offset >= dio_fb_size)
413
+ return;
414
+
415
+ if (offset + size > dio_fb_size)
416
+ size = dio_fb_size - offset;
417
+
418
+ memcpy(par->mmio_vp + offset, par->dio_vp + offset, size);
419
+}
420
+
421
+/* Deferred IO callback */
422
+static void synthvid_deferred_io(struct fb_info *p,
423
+ struct list_head *pagelist)
424
+{
425
+ struct hvfb_par *par = p->par;
426
+ struct page *page;
427
+ unsigned long start, end;
428
+ int y1, y2, miny, maxy;
429
+
430
+ miny = INT_MAX;
431
+ maxy = 0;
432
+
433
+ /*
434
+ * Merge dirty pages. It is possible that last page cross
435
+ * over the end of frame buffer row yres. This is taken care of
436
+ * in synthvid_update function by clamping the y2
437
+ * value to yres.
438
+ */
439
+ list_for_each_entry(page, pagelist, lru) {
440
+ start = page->index << PAGE_SHIFT;
441
+ end = start + PAGE_SIZE - 1;
442
+ y1 = start / p->fix.line_length;
443
+ y2 = end / p->fix.line_length;
444
+ miny = min_t(int, miny, y1);
445
+ maxy = max_t(int, maxy, y2);
446
+
447
+ /* Copy from dio space to mmio address */
448
+ if (par->fb_ready && par->need_docopy)
449
+ hvfb_docopy(par, start, PAGE_SIZE);
450
+ }
451
+
452
+ if (par->fb_ready && par->update)
453
+ synthvid_update(p, 0, miny, p->var.xres, maxy + 1);
454
+}
455
+
456
+static struct fb_deferred_io synthvid_defio = {
457
+ .delay = HZ / 20,
458
+ .deferred_io = synthvid_deferred_io,
459
+};
346460
347461 /*
348462 * Actions on received messages from host:
....@@ -363,6 +477,7 @@
363477
364478 /* Complete the wait event */
365479 if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
480
+ msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE ||
366481 msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
367482 memcpy(par->init_buf, msg, MAX_VMBUS_PKT_SIZE);
368483 complete(&par->wait);
....@@ -409,6 +524,17 @@
409524 } while (bytes_recvd > 0 && ret == 0);
410525 }
411526
527
+/* Check if the ver1 version is equal or greater than ver2 */
528
+static inline bool synthvid_ver_ge(u32 ver1, u32 ver2)
529
+{
530
+ if (SYNTHVID_VER_GET_MAJOR(ver1) > SYNTHVID_VER_GET_MAJOR(ver2) ||
531
+ (SYNTHVID_VER_GET_MAJOR(ver1) == SYNTHVID_VER_GET_MAJOR(ver2) &&
532
+ SYNTHVID_VER_GET_MINOR(ver1) >= SYNTHVID_VER_GET_MINOR(ver2)))
533
+ return true;
534
+
535
+ return false;
536
+}
537
+
412538 /* Check synthetic video protocol version with the host */
413539 static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
414540 {
....@@ -437,6 +563,56 @@
437563 }
438564
439565 par->synthvid_version = ver;
566
+ pr_info("Synthvid Version major %d, minor %d\n",
567
+ SYNTHVID_VER_GET_MAJOR(ver), SYNTHVID_VER_GET_MINOR(ver));
568
+
569
+out:
570
+ return ret;
571
+}
572
+
573
+/* Get current resolution from the host */
574
+static int synthvid_get_supported_resolution(struct hv_device *hdev)
575
+{
576
+ struct fb_info *info = hv_get_drvdata(hdev);
577
+ struct hvfb_par *par = info->par;
578
+ struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
579
+ int ret = 0;
580
+ unsigned long t;
581
+ u8 index;
582
+
583
+ memset(msg, 0, sizeof(struct synthvid_msg));
584
+ msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST;
585
+ msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
586
+ sizeof(struct synthvid_supported_resolution_req);
587
+
588
+ msg->resolution_req.maximum_resolution_count =
589
+ SYNTHVID_MAX_RESOLUTION_COUNT;
590
+ synthvid_send(hdev, msg);
591
+
592
+ t = wait_for_completion_timeout(&par->wait, VSP_TIMEOUT);
593
+ if (!t) {
594
+ pr_err("Time out on waiting resolution response\n");
595
+ ret = -ETIMEDOUT;
596
+ goto out;
597
+ }
598
+
599
+ if (msg->resolution_resp.resolution_count == 0) {
600
+ pr_err("No supported resolutions\n");
601
+ ret = -ENODEV;
602
+ goto out;
603
+ }
604
+
605
+ index = msg->resolution_resp.default_resolution_index;
606
+ if (index >= msg->resolution_resp.resolution_count) {
607
+ pr_err("Invalid resolution index: %d\n", index);
608
+ ret = -ENODEV;
609
+ goto out;
610
+ }
611
+
612
+ screen_width =
613
+ msg->resolution_resp.supported_resolution[index].width;
614
+ screen_height =
615
+ msg->resolution_resp.supported_resolution[index].height;
440616
441617 out:
442618 return ret;
....@@ -457,11 +633,27 @@
457633 }
458634
459635 /* Negotiate the protocol version with host */
460
- if (vmbus_proto_version == VERSION_WS2008 ||
461
- vmbus_proto_version == VERSION_WIN7)
462
- ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
463
- else
636
+ switch (vmbus_proto_version) {
637
+ case VERSION_WIN10:
638
+ case VERSION_WIN10_V5:
639
+ ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);
640
+ if (!ret)
641
+ break;
642
+ fallthrough;
643
+ case VERSION_WIN8:
644
+ case VERSION_WIN8_1:
464645 ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8);
646
+ if (!ret)
647
+ break;
648
+ fallthrough;
649
+ case VERSION_WS2008:
650
+ case VERSION_WIN7:
651
+ ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7);
652
+ break;
653
+ default:
654
+ ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10);
655
+ break;
656
+ }
465657
466658 if (ret) {
467659 pr_err("Synthetic video device version not accepted\n");
....@@ -472,6 +664,12 @@
472664 screen_depth = SYNTHVID_DEPTH_WIN7;
473665 else
474666 screen_depth = SYNTHVID_DEPTH_WIN8;
667
+
668
+ if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) {
669
+ ret = synthvid_get_supported_resolution(hdev);
670
+ if (ret)
671
+ pr_info("Failed to get supported resolution from host, use default\n");
672
+ }
475673
476674 screen_fb_size = hdev->channel->offermsg.offer.
477675 mmio_megabytes * 1024 * 1024;
....@@ -497,7 +695,7 @@
497695 msg->vid_hdr.type = SYNTHVID_VRAM_LOCATION;
498696 msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
499697 sizeof(struct synthvid_vram_location);
500
- msg->vram.user_ctx = msg->vram.vram_gpa = info->fix.smem_start;
698
+ msg->vram.user_ctx = msg->vram.vram_gpa = par->mmio_pp;
501699 msg->vram.is_vram_gpa_specified = 1;
502700 synthvid_send(hdev, msg);
503701
....@@ -507,7 +705,7 @@
507705 ret = -ETIMEDOUT;
508706 goto out;
509707 }
510
- if (msg->vram_ack.user_ctx != info->fix.smem_start) {
708
+ if (msg->vram_ack.user_ctx != par->mmio_pp) {
511709 pr_err("Unable to set VRAM location\n");
512710 ret = -ENODEV;
513711 goto out;
....@@ -524,19 +722,77 @@
524722
525723 /*
526724 * Delayed work callback:
527
- * It is called at HVFB_UPDATE_DELAY or longer time interval to process
528
- * screen updates. It is re-scheduled if further update is necessary.
725
+ * It is scheduled to call whenever update request is received and it has
726
+ * not been called in last HVFB_ONDEMAND_THROTTLE time interval.
529727 */
530728 static void hvfb_update_work(struct work_struct *w)
531729 {
532730 struct hvfb_par *par = container_of(w, struct hvfb_par, dwork.work);
533731 struct fb_info *info = par->info;
732
+ unsigned long flags;
733
+ int x1, x2, y1, y2;
734
+ int j;
534735
535
- if (par->fb_ready)
536
- synthvid_update(info);
736
+ spin_lock_irqsave(&par->delayed_refresh_lock, flags);
737
+ /* Reset the request flag */
738
+ par->delayed_refresh = false;
537739
538
- if (par->update)
539
- schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
740
+ /* Store the dirty rectangle to local variables */
741
+ x1 = par->x1;
742
+ x2 = par->x2;
743
+ y1 = par->y1;
744
+ y2 = par->y2;
745
+
746
+ /* Clear dirty rectangle */
747
+ par->x1 = par->y1 = INT_MAX;
748
+ par->x2 = par->y2 = 0;
749
+
750
+ spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);
751
+
752
+ if (x1 > info->var.xres || x2 > info->var.xres ||
753
+ y1 > info->var.yres || y2 > info->var.yres || x2 <= x1)
754
+ return;
755
+
756
+ /* Copy the dirty rectangle to frame buffer memory */
757
+ if (par->need_docopy)
758
+ for (j = y1; j < y2; j++)
759
+ hvfb_docopy(par,
760
+ j * info->fix.line_length +
761
+ (x1 * screen_depth / 8),
762
+ (x2 - x1) * screen_depth / 8);
763
+
764
+ /* Refresh */
765
+ if (par->fb_ready && par->update)
766
+ synthvid_update(info, x1, y1, x2, y2);
767
+}
768
+
769
+/*
770
+ * Control the on-demand refresh frequency. It schedules a delayed
771
+ * screen update if it has not yet.
772
+ */
773
+static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,
774
+ int x1, int y1, int w, int h)
775
+{
776
+ unsigned long flags;
777
+ int x2 = x1 + w;
778
+ int y2 = y1 + h;
779
+
780
+ spin_lock_irqsave(&par->delayed_refresh_lock, flags);
781
+
782
+ /* Merge dirty rectangle */
783
+ par->x1 = min_t(int, par->x1, x1);
784
+ par->y1 = min_t(int, par->y1, y1);
785
+ par->x2 = max_t(int, par->x2, x2);
786
+ par->y2 = max_t(int, par->y2, y2);
787
+
788
+ /* Schedule a delayed screen update if not yet */
789
+ if (par->delayed_refresh == false) {
790
+ schedule_delayed_work(&par->dwork,
791
+ HVFB_ONDEMAND_THROTTLE);
792
+ par->delayed_refresh = true;
793
+ }
794
+
795
+ spin_unlock_irqrestore(&par->delayed_refresh_lock, flags);
540796 }
541797
542798 static int hvfb_on_panic(struct notifier_block *nb,
....@@ -548,7 +804,9 @@
548804 par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
549805 par->synchronous_fb = true;
550806 info = par->info;
551
- synthvid_update(info);
807
+ if (par->need_docopy)
808
+ hvfb_docopy(par, 0, dio_fb_size);
809
+ synthvid_update(info, 0, 0, INT_MAX, INT_MAX);
552810
553811 return NOTIFY_DONE;
554812 }
....@@ -609,7 +867,10 @@
609867
610868 cfb_fillrect(p, rect);
611869 if (par->synchronous_fb)
612
- synthvid_update(p);
870
+ synthvid_update(p, 0, 0, INT_MAX, INT_MAX);
871
+ else
872
+ hvfb_ondemand_refresh_throttle(par, rect->dx, rect->dy,
873
+ rect->width, rect->height);
613874 }
614875
615876 static void hvfb_cfb_copyarea(struct fb_info *p,
....@@ -619,7 +880,10 @@
619880
620881 cfb_copyarea(p, area);
621882 if (par->synchronous_fb)
622
- synthvid_update(p);
883
+ synthvid_update(p, 0, 0, INT_MAX, INT_MAX);
884
+ else
885
+ hvfb_ondemand_refresh_throttle(par, area->dx, area->dy,
886
+ area->width, area->height);
623887 }
624888
625889 static void hvfb_cfb_imageblit(struct fb_info *p,
....@@ -629,10 +893,13 @@
629893
630894 cfb_imageblit(p, image);
631895 if (par->synchronous_fb)
632
- synthvid_update(p);
896
+ synthvid_update(p, 0, 0, INT_MAX, INT_MAX);
897
+ else
898
+ hvfb_ondemand_refresh_throttle(par, image->dx, image->dy,
899
+ image->width, image->height);
633900 }
634901
635
-static struct fb_ops hvfb_ops = {
902
+static const struct fb_ops hvfb_ops = {
636903 .owner = THIS_MODULE,
637904 .fb_check_var = hvfb_check_var,
638905 .fb_set_par = hvfb_set_par,
....@@ -662,6 +929,8 @@
662929 }
663930
664931 if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN ||
932
+ (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) &&
933
+ (x * y * screen_depth / 8 > screen_fb_size)) ||
665934 (par->synthvid_version == SYNTHVID_VERSION_WIN8 &&
666935 x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) ||
667936 (par->synthvid_version == SYNTHVID_VERSION_WIN7 &&
....@@ -675,6 +944,62 @@
675944 return;
676945 }
677946
947
+/*
948
+ * Allocate enough contiguous physical memory.
949
+ * Return physical address if succeeded or -1 if failed.
950
+ */
951
+static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,
952
+ unsigned int request_size)
953
+{
954
+ struct page *page = NULL;
955
+ dma_addr_t dma_handle;
956
+ void *vmem;
957
+ phys_addr_t paddr = 0;
958
+ unsigned int order = get_order(request_size);
959
+
960
+ if (request_size == 0)
961
+ return -1;
962
+
963
+ if (order < MAX_ORDER) {
964
+ /* Call alloc_pages if the size is less than 2^MAX_ORDER */
965
+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
966
+ if (!page)
967
+ return -1;
968
+
969
+ paddr = (page_to_pfn(page) << PAGE_SHIFT);
970
+ } else {
971
+ /* Allocate from CMA */
972
+ hdev->device.coherent_dma_mask = DMA_BIT_MASK(64);
973
+
974
+ vmem = dma_alloc_coherent(&hdev->device,
975
+ round_up(request_size, PAGE_SIZE),
976
+ &dma_handle,
977
+ GFP_KERNEL | __GFP_NOWARN);
978
+
979
+ if (!vmem)
980
+ return -1;
981
+
982
+ paddr = virt_to_phys(vmem);
983
+ }
984
+
985
+ return paddr;
986
+}
987
+
988
+/* Release contiguous physical memory */
989
+static void hvfb_release_phymem(struct hv_device *hdev,
990
+ phys_addr_t paddr, unsigned int size)
991
+{
992
+ unsigned int order = get_order(size);
993
+
994
+ if (order < MAX_ORDER)
995
+ __free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order);
996
+ else
997
+ dma_free_coherent(&hdev->device,
998
+ round_up(size, PAGE_SIZE),
999
+ phys_to_virt(paddr),
1000
+ paddr);
1001
+}
1002
+
6781003
6791004 /* Get framebuffer memory from Hyper-V video pci space */
6801005 static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
....@@ -683,29 +1008,57 @@
6831008 struct pci_dev *pdev = NULL;
6841009 void __iomem *fb_virt;
6851010 int gen2vm = efi_enabled(EFI_BOOT);
686
- resource_size_t pot_start, pot_end;
1011
+ phys_addr_t paddr;
6871012 int ret;
6881013
689
- if (gen2vm) {
690
- pot_start = 0;
691
- pot_end = -1;
692
- } else {
1014
+ info->apertures = alloc_apertures(1);
1015
+ if (!info->apertures)
1016
+ return -ENOMEM;
1017
+
1018
+ if (!gen2vm) {
6931019 pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
694
- PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
1020
+ PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
6951021 if (!pdev) {
6961022 pr_err("Unable to find PCI Hyper-V video\n");
6971023 return -ENODEV;
6981024 }
6991025
700
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
701
- pci_resource_len(pdev, 0) < screen_fb_size)
702
- goto err1;
1026
+ info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
1027
+ info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
7031028
704
- pot_end = pci_resource_end(pdev, 0);
705
- pot_start = pot_end - screen_fb_size + 1;
1029
+ /*
1030
+ * For Gen 1 VM, we can directly use the contiguous memory
1031
+ * from VM. If we succeed, deferred IO happens directly
1032
+ * on this allocated framebuffer memory, avoiding extra
1033
+ * memory copy.
1034
+ */
1035
+ paddr = hvfb_get_phymem(hdev, screen_fb_size);
1036
+ if (paddr != (phys_addr_t) -1) {
1037
+ par->mmio_pp = paddr;
1038
+ par->mmio_vp = par->dio_vp = __va(paddr);
1039
+
1040
+ info->fix.smem_start = paddr;
1041
+ info->fix.smem_len = screen_fb_size;
1042
+ info->screen_base = par->mmio_vp;
1043
+ info->screen_size = screen_fb_size;
1044
+
1045
+ par->need_docopy = false;
1046
+ goto getmem_done;
1047
+ }
1048
+ pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n");
1049
+ } else {
1050
+ info->apertures->ranges[0].base = screen_info.lfb_base;
1051
+ info->apertures->ranges[0].size = screen_info.lfb_size;
7061052 }
7071053
708
- ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end,
1054
+ /*
1055
+ * Cannot use the contiguous physical memory.
1056
+ * Allocate mmio space for framebuffer.
1057
+ */
1058
+ dio_fb_size =
1059
+ screen_width * screen_height * screen_depth / 8;
1060
+
1061
+ ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1,
7091062 screen_fb_size, 0x100000, true);
7101063 if (ret != 0) {
7111064 pr_err("Unable to allocate framebuffer memory\n");
....@@ -713,33 +1066,41 @@
7131066 }
7141067
7151068 /*
716
- * Map the VRAM cacheable for performance.
1069
+ * Map the VRAM cacheable for performance. This is also required for
1070
+ * VM Connect to display properly for ARM64 Linux VM, as the host also
1071
+ * maps the VRAM cacheable.
7171072 */
718
- fb_virt = ioremap_wc(par->mem->start, screen_fb_size);
1073
+ fb_virt = ioremap_cache(par->mem->start, screen_fb_size);
7191074 if (!fb_virt)
7201075 goto err2;
7211076
722
- info->apertures = alloc_apertures(1);
723
- if (!info->apertures)
1077
+ /* Allocate memory for deferred IO */
1078
+ par->dio_vp = vzalloc(round_up(dio_fb_size, PAGE_SIZE));
1079
+ if (par->dio_vp == NULL)
7241080 goto err3;
7251081
726
- if (gen2vm) {
727
- info->apertures->ranges[0].base = screen_info.lfb_base;
728
- info->apertures->ranges[0].size = screen_info.lfb_size;
729
- remove_conflicting_framebuffers(info->apertures,
730
- KBUILD_MODNAME, false);
731
- } else {
732
- info->apertures->ranges[0].base = pci_resource_start(pdev, 0);
733
- info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
734
- }
1082
+ /* Physical address of FB device */
1083
+ par->mmio_pp = par->mem->start;
1084
+ /* Virtual address of FB device */
1085
+ par->mmio_vp = (unsigned char *) fb_virt;
7351086
7361087 info->fix.smem_start = par->mem->start;
737
- info->fix.smem_len = screen_fb_size;
738
- info->screen_base = fb_virt;
739
- info->screen_size = screen_fb_size;
1088
+ info->fix.smem_len = dio_fb_size;
1089
+ info->screen_base = par->dio_vp;
1090
+ info->screen_size = dio_fb_size;
7401091
741
- if (!gen2vm)
1092
+getmem_done:
1093
+ remove_conflicting_framebuffers(info->apertures,
1094
+ KBUILD_MODNAME, false);
1095
+
1096
+ if (gen2vm) {
1097
+ /* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */
1098
+ screen_info.lfb_size = 0;
1099
+ screen_info.lfb_base = 0;
1100
+ screen_info.orig_video_isVGA = 0;
1101
+ } else {
7421102 pci_dev_put(pdev);
1103
+ }
7431104
7441105 return 0;
7451106
....@@ -756,12 +1117,19 @@
7561117 }
7571118
7581119 /* Release the framebuffer */
759
-static void hvfb_putmem(struct fb_info *info)
1120
+static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)
7601121 {
7611122 struct hvfb_par *par = info->par;
7621123
763
- iounmap(info->screen_base);
764
- vmbus_free_mmio(par->mem->start, screen_fb_size);
1124
+ if (par->need_docopy) {
1125
+ vfree(par->dio_vp);
1126
+ iounmap(info->screen_base);
1127
+ vmbus_free_mmio(par->mem->start, screen_fb_size);
1128
+ } else {
1129
+ hvfb_release_phymem(hdev, info->fix.smem_start,
1130
+ screen_fb_size);
1131
+ }
1132
+
7651133 par->mem = NULL;
7661134 }
7671135
....@@ -774,16 +1142,20 @@
7741142 int ret;
7751143
7761144 info = framebuffer_alloc(sizeof(struct hvfb_par), &hdev->device);
777
- if (!info) {
778
- pr_err("No memory for framebuffer info\n");
1145
+ if (!info)
7791146 return -ENOMEM;
780
- }
7811147
7821148 par = info->par;
7831149 par->info = info;
7841150 par->fb_ready = false;
1151
+ par->need_docopy = true;
7851152 init_completion(&par->wait);
7861153 INIT_DELAYED_WORK(&par->dwork, hvfb_update_work);
1154
+
1155
+ par->delayed_refresh = false;
1156
+ spin_lock_init(&par->delayed_refresh_lock);
1157
+ par->x1 = par->y1 = INT_MAX;
1158
+ par->x2 = par->y2 = 0;
7871159
7881160 /* Connect to VSP */
7891161 hv_set_drvdata(hdev, info);
....@@ -793,16 +1165,15 @@
7931165 goto error1;
7941166 }
7951167
1168
+ hvfb_get_option(info);
1169
+ pr_info("Screen resolution: %dx%d, Color depth: %d, Frame buffer size: %d\n",
1170
+ screen_width, screen_height, screen_depth, screen_fb_size);
1171
+
7961172 ret = hvfb_getmem(hdev, info);
7971173 if (ret) {
7981174 pr_err("No memory for framebuffer\n");
7991175 goto error2;
8001176 }
801
-
802
- hvfb_get_option(info);
803
- pr_info("Screen resolution: %dx%d, Color depth: %d\n",
804
- screen_width, screen_height, screen_depth);
805
-
8061177
8071178 /* Set up fb_info */
8081179 info->flags = FBINFO_DEFAULT;
....@@ -837,6 +1208,10 @@
8371208 info->fbops = &hvfb_ops;
8381209 info->pseudo_palette = par->pseudo_palette;
8391210
1211
+ /* Initialize deferred IO */
1212
+ info->fbdefio = &synthvid_defio;
1213
+ fb_deferred_io_init(info);
1214
+
8401215 /* Send config to host */
8411216 ret = synthvid_send_config(hdev);
8421217 if (ret)
....@@ -858,7 +1233,8 @@
8581233 return 0;
8591234
8601235 error:
861
- hvfb_putmem(info);
1236
+ fb_deferred_io_cleanup(info);
1237
+ hvfb_putmem(hdev, info);
8621238 error2:
8631239 vmbus_close(hdev->channel);
8641240 error1:
....@@ -880,16 +1256,75 @@
8801256 par->update = false;
8811257 par->fb_ready = false;
8821258
1259
+ fb_deferred_io_cleanup(info);
1260
+
8831261 unregister_framebuffer(info);
8841262 cancel_delayed_work_sync(&par->dwork);
8851263
8861264 vmbus_close(hdev->channel);
8871265 hv_set_drvdata(hdev, NULL);
8881266
889
- hvfb_putmem(info);
1267
+ hvfb_putmem(hdev, info);
8901268 framebuffer_release(info);
8911269
8921270 return 0;
1271
+}
1272
+
1273
+static int hvfb_suspend(struct hv_device *hdev)
1274
+{
1275
+ struct fb_info *info = hv_get_drvdata(hdev);
1276
+ struct hvfb_par *par = info->par;
1277
+
1278
+ console_lock();
1279
+
1280
+ /* 1 means do suspend */
1281
+ fb_set_suspend(info, 1);
1282
+
1283
+ cancel_delayed_work_sync(&par->dwork);
1284
+ cancel_delayed_work_sync(&info->deferred_work);
1285
+
1286
+ par->update_saved = par->update;
1287
+ par->update = false;
1288
+ par->fb_ready = false;
1289
+
1290
+ vmbus_close(hdev->channel);
1291
+
1292
+ console_unlock();
1293
+
1294
+ return 0;
1295
+}
1296
+
1297
+static int hvfb_resume(struct hv_device *hdev)
1298
+{
1299
+ struct fb_info *info = hv_get_drvdata(hdev);
1300
+ struct hvfb_par *par = info->par;
1301
+ int ret;
1302
+
1303
+ console_lock();
1304
+
1305
+ ret = synthvid_connect_vsp(hdev);
1306
+ if (ret != 0)
1307
+ goto out;
1308
+
1309
+ ret = synthvid_send_config(hdev);
1310
+ if (ret != 0) {
1311
+ vmbus_close(hdev->channel);
1312
+ goto out;
1313
+ }
1314
+
1315
+ par->fb_ready = true;
1316
+ par->update = par->update_saved;
1317
+
1318
+ schedule_delayed_work(&info->deferred_work, info->fbdefio->delay);
1319
+ schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
1320
+
1321
+ /* 0 means do resume */
1322
+ fb_set_suspend(info, 0);
1323
+
1324
+out:
1325
+ console_unlock();
1326
+
1327
+ return ret;
8931328 }
8941329
8951330
....@@ -915,6 +1350,8 @@
9151350 .id_table = id_table,
9161351 .probe = hvfb_probe,
9171352 .remove = hvfb_remove,
1353
+ .suspend = hvfb_suspend,
1354
+ .resume = hvfb_resume,
9181355 .driver = {
9191356 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
9201357 },