diff options
-rw-r--r-- | drivers/video/fbdev/hyperv_fb.c | 62 |
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 | ||
229 | static uint screen_width = HVFB_WIDTH; | 234 | static 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 | ||
540 | static 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 | ||
603 | static 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 | |||
613 | static 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 | |||
623 | static 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 | |||
585 | static struct fb_ops hvfb_ops = { | 633 | static 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 | ||
806 | error: | 859 | error: |
@@ -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 | ||