vt(4): Make sure vt_switch_timer() has a sleepable context.

Fixes the following panic backtrace:

panic()
usbhid_sync_xfer()
usbhid_set_report()
hid_set_report()
hidbus_write()
hid_write()
hkbd_set_leds()
hkbd_ioctl_locked()
hkbd_ioctl_locked()
hkbd_ioctl()
kbdmux_ioctl()
vt_window_switch()
vt_switch_timer()

Differential Revision:	https://reviews.freebsd.org/D36715
MFC after:	1 week
Sponsored by:	NVIDIA Networking
This commit is contained in:
Hans Petter Selasky 2022-09-26 17:10:50 +02:00
parent 78aeba26e8
commit 2cce9aa078
3 changed files with 8 additions and 9 deletions

View File

@ -48,6 +48,7 @@
#include <sys/terminal.h>
#include <sys/sysctl.h>
#include <sys/font.h>
#include <sys/taskqueue.h>
#include "opt_syscons.h"
#include "opt_splash.h"
@ -306,7 +307,7 @@ struct vt_window {
pid_t vw_pid; /* Terminal holding process */
struct proc *vw_proc;
struct vt_mode vw_smode; /* switch mode */
struct callout vw_proc_dead_timer;
struct timeout_task vw_timeout_task_dead;
struct vt_window *vw_switch_to;
int vw_bell_pitch; /* (?) Bell pitch */
sbintime_t vw_bell_duration; /* (?) Bell duration */

View File

@ -338,7 +338,7 @@ vt_suspend_flush_timer(struct vt_device *vd)
}
static void
vt_switch_timer(void *arg)
vt_switch_timer(void *arg, int pending)
{
(void)vt_late_window_switch((struct vt_window *)arg);
@ -442,8 +442,7 @@ vt_window_preswitch(struct vt_window *vw, struct vt_window *curvw)
DPRINTF(40, "%s\n", __func__);
curvw->vw_switch_to = vw;
/* Set timer to allow switch in case when process hang. */
callout_reset(&vw->vw_proc_dead_timer, hz * vt_deadtimer,
vt_switch_timer, (void *)vw);
taskqueue_enqueue_timeout(taskqueue_thread, &vw->vw_timeout_task_dead, hz * vt_deadtimer);
/* Notify process about vt switch attempt. */
DPRINTF(30, "%s: Notify process.\n", __func__);
signal_vt_rel(curvw);
@ -466,7 +465,7 @@ vt_late_window_switch(struct vt_window *vw)
struct vt_window *curvw;
int ret;
callout_stop(&vw->vw_proc_dead_timer);
taskqueue_cancel_timeout(taskqueue_thread, &vw->vw_timeout_task_dead, NULL);
ret = vt_window_switch(vw);
if (ret != 0) {
@ -2045,7 +2044,7 @@ finish_vt_rel(struct vt_window *vw, int release, int *s)
if (vw->vw_flags & VWF_SWWAIT_REL) {
vw->vw_flags &= ~VWF_SWWAIT_REL;
if (release) {
callout_drain(&vw->vw_proc_dead_timer);
taskqueue_drain_timeout(taskqueue_thread, &vw->vw_timeout_task_dead);
(void)vt_late_window_switch(vw->vw_switch_to);
}
return (0);
@ -2929,7 +2928,7 @@ vt_allocate_window(struct vt_device *vd, unsigned int window)
terminal_set_winsize(tm, &wsz);
vd->vd_windows[window] = vw;
callout_init(&vw->vw_proc_dead_timer, 1);
TIMEOUT_TASK_INIT(taskqueue_thread, &vw->vw_timeout_task_dead, 0, &vt_switch_timer, vw);
return (vw);
}
@ -2953,7 +2952,7 @@ vt_upgrade(struct vt_device *vd)
vw = vt_allocate_window(vd, i);
}
if (!(vw->vw_flags & VWF_READY)) {
callout_init(&vw->vw_proc_dead_timer, 1);
TIMEOUT_TASK_INIT(taskqueue_thread, &vw->vw_timeout_task_dead, 0, &vt_switch_timer, vw);
terminal_maketty(vw->vw_terminal, "v%r", VT_UNIT(vw));
vw->vw_flags |= VWF_READY;
if (vw->vw_flags & VWF_CONSOLE) {

View File

@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/smp.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <sys/terminal.h>
#include <dev/vt/vt.h>