vt(4): Use power_{suspend,resume} event handlers to implement
suspend/resume The goal is to avoid that the vt(4) resume happens before the video display is resumed. The original patch was provided by Andriy Gapon. This new patch registers the handlers in vt_upgrade(). This is done once, thanks to the VDF_ASYNC flag. I abused this flag because it was already abused by the keyboard allocation. The event handlers then call the backend if it provides callbacks for suspend/resume. Differential Revision: https://reviews.freebsd.org/D1004 On behalf of: dumbbell MFC after: 2 weeks
This commit is contained in:
parent
cda374fe00
commit
6dfa4578d6
@ -332,22 +332,6 @@ fbd_detach(device_t dev)
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
fbd_suspend(device_t dev)
|
||||
{
|
||||
|
||||
vt_fb_suspend();
|
||||
return (bus_generic_suspend(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
fbd_resume(device_t dev)
|
||||
{
|
||||
|
||||
vt_fb_resume();
|
||||
return (bus_generic_resume(dev));
|
||||
}
|
||||
|
||||
static device_method_t fbd_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, fbd_probe),
|
||||
@ -355,8 +339,6 @@ static device_method_t fbd_methods[] = {
|
||||
DEVMETHOD(device_detach, fbd_detach),
|
||||
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, fbd_suspend),
|
||||
DEVMETHOD(device_resume, fbd_resume),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -53,6 +53,8 @@ static struct vt_driver vt_fb_driver = {
|
||||
.vd_priority = VD_PRIORITY_GENERIC+10,
|
||||
.vd_fb_ioctl = vt_fb_ioctl,
|
||||
.vd_fb_mmap = vt_fb_mmap,
|
||||
.vd_suspend = vt_fb_suspend,
|
||||
.vd_resume = vt_fb_resume,
|
||||
};
|
||||
|
||||
VT_DRIVER_DECLARE(vt_fb, vt_fb_driver);
|
||||
@ -450,15 +452,15 @@ vt_fb_attach(struct fb_info *info)
|
||||
}
|
||||
|
||||
void
|
||||
vt_fb_resume(void)
|
||||
vt_fb_suspend(struct vt_device *vd)
|
||||
{
|
||||
|
||||
vt_resume();
|
||||
vt_suspend(vd);
|
||||
}
|
||||
|
||||
void
|
||||
vt_fb_suspend(void)
|
||||
vt_fb_resume(struct vt_device *vd)
|
||||
{
|
||||
|
||||
vt_suspend();
|
||||
vt_resume(vd);
|
||||
}
|
||||
|
@ -33,8 +33,8 @@
|
||||
#define _DEV_VT_HW_FB_VT_FB_H_
|
||||
/* Generic framebuffer interface call vt_fb_attach to init VT(9) */
|
||||
int vt_fb_attach(struct fb_info *info);
|
||||
void vt_fb_resume(void);
|
||||
void vt_fb_suspend(void);
|
||||
void vt_fb_resume(struct vt_device *vd);
|
||||
void vt_fb_suspend(struct vt_device *vd);
|
||||
|
||||
vd_init_t vt_fb_init;
|
||||
vd_blank_t vt_fb_blank;
|
||||
|
@ -90,8 +90,6 @@ SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RWTUN, &vt_##_name, _default,\
|
||||
struct vt_driver;
|
||||
|
||||
void vt_allocate(struct vt_driver *, void *);
|
||||
void vt_resume(void);
|
||||
void vt_suspend(void);
|
||||
|
||||
typedef unsigned int vt_axis_t;
|
||||
|
||||
@ -162,6 +160,9 @@ struct vt_device {
|
||||
#define VD_PASTEBUFSZ(vd) ((vd)->vd_pastebuf.vpb_bufsz)
|
||||
#define VD_PASTEBUFLEN(vd) ((vd)->vd_pastebuf.vpb_len)
|
||||
|
||||
void vt_resume(struct vt_device *vd);
|
||||
void vt_suspend(struct vt_device *vd);
|
||||
|
||||
/*
|
||||
* Per-window terminal screen buffer.
|
||||
*
|
||||
@ -314,6 +315,8 @@ typedef int vd_fb_mmap_t(struct vt_device *, vm_ooffset_t, vm_paddr_t *, int,
|
||||
typedef void vd_drawrect_t(struct vt_device *, int, int, int, int, int,
|
||||
term_color_t);
|
||||
typedef void vd_setpixel_t(struct vt_device *, int, int, term_color_t);
|
||||
typedef void vd_suspend_t(struct vt_device *);
|
||||
typedef void vd_resume_t(struct vt_device *);
|
||||
|
||||
struct vt_driver {
|
||||
char vd_name[16];
|
||||
@ -337,6 +340,10 @@ struct vt_driver {
|
||||
/* Update display setting on vt switch. */
|
||||
vd_postswitch_t *vd_postswitch;
|
||||
|
||||
/* Suspend/resume handlers. */
|
||||
vd_suspend_t *vd_suspend;
|
||||
vd_resume_t *vd_resume;
|
||||
|
||||
/* Priority to know which one can override */
|
||||
int vd_priority;
|
||||
#define VD_PRIORITY_DUMB 10
|
||||
|
@ -167,6 +167,8 @@ static void vt_update_static(void *);
|
||||
#ifndef SC_NO_CUTPASTE
|
||||
static void vt_mouse_paste(void);
|
||||
#endif
|
||||
static void vt_suspend_handler(void *priv);
|
||||
static void vt_resume_handler(void *priv);
|
||||
|
||||
SET_DECLARE(vt_drv_set, struct vt_driver);
|
||||
|
||||
@ -2552,6 +2554,12 @@ vt_upgrade(struct vt_device *vd)
|
||||
vd->vd_flags |= VDF_ASYNC;
|
||||
callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd);
|
||||
vd->vd_timer_armed = 1;
|
||||
|
||||
/* Register suspend/resume handlers. */
|
||||
EVENTHANDLER_REGISTER(power_suspend, vt_suspend_handler, vd,
|
||||
EVENTHANDLER_PRI_ANY);
|
||||
EVENTHANDLER_REGISTER(power_resume, vt_resume_handler, vd,
|
||||
EVENTHANDLER_PRI_ANY);
|
||||
}
|
||||
|
||||
VT_UNLOCK(vd);
|
||||
@ -2655,26 +2663,54 @@ vt_allocate(struct vt_driver *drv, void *softc)
|
||||
termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal);
|
||||
}
|
||||
|
||||
void
|
||||
vt_suspend()
|
||||
static void
|
||||
vt_suspend_handler(void *priv)
|
||||
{
|
||||
struct vt_device *vd;
|
||||
|
||||
vd = priv;
|
||||
if (vd->vd_driver != NULL && vd->vd_driver->vd_suspend != NULL)
|
||||
vd->vd_driver->vd_suspend(vd);
|
||||
}
|
||||
|
||||
static void
|
||||
vt_resume_handler(void *priv)
|
||||
{
|
||||
struct vt_device *vd;
|
||||
|
||||
vd = priv;
|
||||
if (vd->vd_driver != NULL && vd->vd_driver->vd_resume != NULL)
|
||||
vd->vd_driver->vd_resume(vd);
|
||||
}
|
||||
|
||||
void
|
||||
vt_suspend(struct vt_device *vd)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (vt_suspendswitch == 0)
|
||||
return;
|
||||
/* Save current window. */
|
||||
main_vd->vd_savedwindow = main_vd->vd_curwindow;
|
||||
vd->vd_savedwindow = vd->vd_curwindow;
|
||||
/* Ask holding process to free window and switch to console window */
|
||||
vt_proc_window_switch(main_vd->vd_windows[VT_CONSWINDOW]);
|
||||
vt_proc_window_switch(vd->vd_windows[VT_CONSWINDOW]);
|
||||
|
||||
/* Wait for the window switch to complete. */
|
||||
error = 0;
|
||||
VT_LOCK(vd);
|
||||
while (vd->vd_curwindow != vd->vd_windows[VT_CONSWINDOW] && error == 0)
|
||||
error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock);
|
||||
VT_UNLOCK(vd);
|
||||
}
|
||||
|
||||
void
|
||||
vt_resume()
|
||||
vt_resume(struct vt_device *vd)
|
||||
{
|
||||
|
||||
if (vt_suspendswitch == 0)
|
||||
return;
|
||||
/* Switch back to saved window */
|
||||
if (main_vd->vd_savedwindow != NULL)
|
||||
vt_proc_window_switch(main_vd->vd_savedwindow);
|
||||
main_vd->vd_savedwindow = NULL;
|
||||
if (vd->vd_savedwindow != NULL)
|
||||
vt_proc_window_switch(vd->vd_savedwindow);
|
||||
vd->vd_savedwindow = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user