> -----Original Message----- > From: driverdev-devel-bounces@xxxxxxxxxxxxxxxxxxxxxx [mailto:driverdev- > devel-bounces@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of Dexuan Cui > Sent: Friday, June 27, 2014 5:35 AM > To: gregkh@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; driverdev- > devel@xxxxxxxxxxxxxxxxxxxxxx; plagnioj@xxxxxxxxxxxx; > tomi.valkeinen@xxxxxx; linux-fbdev@xxxxxxxxxxxxxxx; olaf@xxxxxxxxx; > apw@xxxxxxxxxxxxx; jasowang@xxxxxxxxxx > Cc: Haiyang Zhang > Subject: [PATCH v2] video: hyperv: hyperv_fb: refresh the VM screen by force > on VM panic > > Currently the VSC has no chance to notify the VSP of the dirty rectangle on > VM > panic because the notification work is done in a workqueue, and in panic() > the > kernel typically ends up in an infinite loop, and a typical kernel config has > CONFIG_PREEMPT_VOLUNTARY=y and CONFIG_PREEMPT is not set, so a > context switch > can't happen in panic() and the workqueue won't have a chance to run. As a > result, the VM Connection window can't refresh until it's closed and we > re-connect to the VM. > > We can register a handler on panic_notifier_list: the handler can notify > the VSC and switch the framebuffer driver to a "synchronous mode", > meaning > the VSC flushes any future framebuffer change to the VSP immediately. > > v2: removed the MS-TFS line in the commit message > > Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx> > Reviewed-by: Haiyang Zhang <haiyangz@xxxxxxxxxxxxx> Hi Greg, Tomi, Jean and all, Any new comment for the patch? Thanks, -- Dexuan > --- > drivers/video/fbdev/hyperv_fb.c | 58 > ++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 55 insertions(+), 3 deletions(-) > > diff --git a/drivers/video/fbdev/hyperv_fb.c > b/drivers/video/fbdev/hyperv_fb.c > index e23392e..291d171 100644 > --- a/drivers/video/fbdev/hyperv_fb.c > +++ b/drivers/video/fbdev/hyperv_fb.c > @@ -226,11 +226,16 @@ struct hvfb_par { > u8 recv_buf[MAX_VMBUS_PKT_SIZE]; > }; > > +static struct fb_info *hvfb_info; > + > static uint screen_width = HVFB_WIDTH; > static uint screen_height = HVFB_HEIGHT; > static uint screen_depth; > static uint screen_fb_size; > > +/* If true, the VSC notifies the VSP on every framebuffer change */ > +static bool synchronous_fb; > + > /* Send message to Hyper-V host */ > static inline int synthvid_send(struct hv_device *hdev, > struct synthvid_msg *msg) > @@ -532,6 +537,20 @@ static void hvfb_update_work(struct work_struct *w) > schedule_delayed_work(&par->dwork, > HVFB_UPDATE_DELAY); > } > > +static int hvfb_on_panic(struct notifier_block *nb, > + unsigned long e, void *p) > +{ > + if (hvfb_info) > + synthvid_update(hvfb_info); > + > + synchronous_fb = true; > + > + return NOTIFY_DONE; > +} > + > +static struct notifier_block hvfb_panic_nb = { > + .notifier_call = hvfb_on_panic, > +}; > > /* Framebuffer operation handlers */ > > @@ -582,14 +601,41 @@ static int hvfb_blank(int blank, struct fb_info *info) > return 1; /* get fb_blank to set the colormap to all black */ > } > > +static void hvfb_cfb_fillrect(struct fb_info *p, > + const struct fb_fillrect *rect) > +{ > + cfb_fillrect(p, rect); > + > + if (unlikely(synchronous_fb)) > + synthvid_update(p); > +} > + > +static void hvfb_cfb_copyarea(struct fb_info *p, > + const struct fb_copyarea *area) > +{ > + cfb_copyarea(p, area); > + > + if (unlikely(synchronous_fb)) > + synthvid_update(p); > +} > + > +static void hvfb_cfb_imageblit(struct fb_info *p, > + const struct fb_image *image) > +{ > + cfb_imageblit(p, image); > + > + if (unlikely(synchronous_fb)) > + synthvid_update(p); > +} > + > static struct fb_ops hvfb_ops = { > .owner = THIS_MODULE, > .fb_check_var = hvfb_check_var, > .fb_set_par = hvfb_set_par, > .fb_setcolreg = hvfb_setcolreg, > - .fb_fillrect = cfb_fillrect, > - .fb_copyarea = cfb_copyarea, > - .fb_imageblit = cfb_imageblit, > + .fb_fillrect = hvfb_cfb_fillrect, > + .fb_copyarea = hvfb_cfb_copyarea, > + .fb_imageblit = hvfb_cfb_imageblit, > .fb_blank = hvfb_blank, > }; > > @@ -801,6 +847,9 @@ static int hvfb_probe(struct hv_device *hdev, > > par->fb_ready = true; > > + hvfb_info = info; > + atomic_notifier_chain_register(&panic_notifier_list, > &hvfb_panic_nb); > + > return 0; > > error: > @@ -820,6 +869,9 @@ static int hvfb_remove(struct hv_device *hdev) > struct fb_info *info = hv_get_drvdata(hdev); > struct hvfb_par *par = info->par; > > + atomic_notifier_chain_unregister(&panic_notifier_list, > &hvfb_panic_nb); > + hvfb_info = NULL; > + > par->update = false; > par->fb_ready = false; > > -- > 1.9.1 > > _______________________________________________ > devel mailing list > devel@xxxxxxxxxxxxxxxxxxxxxx > http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel