summaryrefslogtreecommitdiffstats
path: root/sys/dev/vt
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2015-01-27 15:28:46 +0000
committeravg <avg@FreeBSD.org>2015-01-27 15:28:46 +0000
commitfeecf521e9468e3ccff20fcbe45d9a810f0563cf (patch)
tree36dbe096d99a8bf61a83acd0afff2656a27318d4 /sys/dev/vt
parentda0490b2e8a0b49115c136dfbd1b51040bd86e65 (diff)
downloadFreeBSD-src-feecf521e9468e3ccff20fcbe45d9a810f0563cf.zip
FreeBSD-src-feecf521e9468e3ccff20fcbe45d9a810f0563cf.tar.gz
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
Diffstat (limited to 'sys/dev/vt')
-rw-r--r--sys/dev/vt/hw/fb/vt_fb.c10
-rw-r--r--sys/dev/vt/hw/fb/vt_fb.h4
-rw-r--r--sys/dev/vt/vt.h11
-rw-r--r--sys/dev/vt/vt_core.c50
4 files changed, 60 insertions, 15 deletions
diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c
index 044b641..5a0fe4f 100644
--- a/sys/dev/vt/hw/fb/vt_fb.c
+++ b/sys/dev/vt/hw/fb/vt_fb.c
@@ -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);
}
diff --git a/sys/dev/vt/hw/fb/vt_fb.h b/sys/dev/vt/hw/fb/vt_fb.h
index 43ce2b7..ac18cff 100644
--- a/sys/dev/vt/hw/fb/vt_fb.h
+++ b/sys/dev/vt/hw/fb/vt_fb.h
@@ -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;
diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h
index 67fcf1e..0ad8ab5 100644
--- a/sys/dev/vt/vt.h
+++ b/sys/dev/vt/vt.h
@@ -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
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index bf0ae1a..d700730 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -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);
}
+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()
+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;
}
OpenPOWER on IntegriCloud