aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/hyperv_fb.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index e23392ec5af3..569e7562fa3d 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -224,6 +224,11 @@ struct hvfb_par {
224 u32 pseudo_palette[16]; 224 u32 pseudo_palette[16];
225 u8 init_buf[MAX_VMBUS_PKT_SIZE]; 225 u8 init_buf[MAX_VMBUS_PKT_SIZE];
226 u8 recv_buf[MAX_VMBUS_PKT_SIZE]; 226 u8 recv_buf[MAX_VMBUS_PKT_SIZE];
227
228 /* If true, the VSC notifies the VSP on every framebuffer change */
229 bool synchronous_fb;
230
231 struct notifier_block hvfb_panic_nb;
227}; 232};
228 233
229static uint screen_width = HVFB_WIDTH; 234static uint screen_width = HVFB_WIDTH;
@@ -532,6 +537,19 @@ static void hvfb_update_work(struct work_struct *w)
532 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY); 537 schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
533} 538}
534 539
540static int hvfb_on_panic(struct notifier_block *nb,
541 unsigned long e, void *p)
542{
543 struct hvfb_par *par;
544 struct fb_info *info;
545
546 par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
547 par->synchronous_fb = true;
548 info = par->info;
549 synthvid_update(info);
550
551 return NOTIFY_DONE;
552}
535 553
536/* Framebuffer operation handlers */ 554/* Framebuffer operation handlers */
537 555
@@ -582,14 +600,44 @@ static int hvfb_blank(int blank, struct fb_info *info)
582 return 1; /* get fb_blank to set the colormap to all black */ 600 return 1; /* get fb_blank to set the colormap to all black */
583} 601}
584 602
603static void hvfb_cfb_fillrect(struct fb_info *p,
604 const struct fb_fillrect *rect)
605{
606 struct hvfb_par *par = p->par;
607
608 cfb_fillrect(p, rect);
609 if (par->synchronous_fb)
610 synthvid_update(p);
611}
612
613static void hvfb_cfb_copyarea(struct fb_info *p,
614 const struct fb_copyarea *area)
615{
616 struct hvfb_par *par = p->par;
617
618 cfb_copyarea(p, area);
619 if (par->synchronous_fb)
620 synthvid_update(p);
621}
622
623static void hvfb_cfb_imageblit(struct fb_info *p,
624 const struct fb_image *image)
625{
626 struct hvfb_par *par = p->par;
627
628 cfb_imageblit(p, image);
629 if (par->synchronous_fb)
630 synthvid_update(p);
631}
632
585static struct fb_ops hvfb_ops = { 633static struct fb_ops hvfb_ops = {
586 .owner = THIS_MODULE, 634 .owner = THIS_MODULE,
587 .fb_check_var = hvfb_check_var, 635 .fb_check_var = hvfb_check_var,
588 .fb_set_par = hvfb_set_par, 636 .fb_set_par = hvfb_set_par,
589 .fb_setcolreg = hvfb_setcolreg, 637 .fb_setcolreg = hvfb_setcolreg,
590 .fb_fillrect = cfb_fillrect, 638 .fb_fillrect = hvfb_cfb_fillrect,
591 .fb_copyarea = cfb_copyarea, 639 .fb_copyarea = hvfb_cfb_copyarea,
592 .fb_imageblit = cfb_imageblit, 640 .fb_imageblit = hvfb_cfb_imageblit,
593 .fb_blank = hvfb_blank, 641 .fb_blank = hvfb_blank,
594}; 642};
595 643
@@ -801,6 +849,11 @@ static int hvfb_probe(struct hv_device *hdev,
801 849
802 par->fb_ready = true; 850 par->fb_ready = true;
803 851
852 par->synchronous_fb = false;
853 par->hvfb_panic_nb.notifier_call = hvfb_on_panic;
854 atomic_notifier_chain_register(&panic_notifier_list,
855 &par->hvfb_panic_nb);
856
804 return 0; 857 return 0;
805 858
806error: 859error:
@@ -820,6 +873,9 @@ static int hvfb_remove(struct hv_device *hdev)
820 struct fb_info *info = hv_get_drvdata(hdev); 873 struct fb_info *info = hv_get_drvdata(hdev);
821 struct hvfb_par *par = info->par; 874 struct hvfb_par *par = info->par;
822 875
876 atomic_notifier_chain_unregister(&panic_notifier_list,
877 &par->hvfb_panic_nb);
878
823 par->update = false; 879 par->update = false;
824 par->fb_ready = false; 880 par->fb_ready = false;
825 881