diff --git a/sys/dev/misc/syscons/syscons.c b/sys/dev/misc/syscons/syscons.c index 618cfe4..ab57ff4 100644 --- a/sys/dev/misc/syscons/syscons.c +++ b/sys/dev/misc/syscons/syscons.c @@ -136,7 +136,8 @@ static cdev_t cctl_dev; static timeout_t blink_screen_callout; #endif static void sc_blink_screen(scr_stat *scp); -static struct mtx syscons_mtx = MTX_INITIALIZER; +static struct sc_lock sc_lock = { MTX_INITIALIZER, 0 }; + /* prototypes */ static int scvidprobe(int unit, int flags, int cons); @@ -197,7 +198,7 @@ static int sc_allocate_keyboard(sc_softc_t *sc, int unit); static void syscons_lock(void) { - mtx_spinlock(&syscons_mtx); + mtx_spinlock(&sc_lock.syscons_mtx); } /* @@ -206,15 +207,36 @@ syscons_lock(void) static int syscons_lock_nonblock(void) { - return(mtx_spinlock_try(&syscons_mtx)); + return(mtx_spinlock_try(&sc_lock.syscons_mtx)); } static void syscons_unlock(void) { - mtx_spinunlock(&syscons_mtx); + mtx_spinunlock(&sc_lock.syscons_mtx); +} + +/* + * Unlocks if specified before + */ +static void +syscons_unlock_needed(void) +{ + if (sc_lock.flags & SC_NEEDS_UNLOCK) + syscons_unlock(); +} + +/* + * Locks if previously it was needed to unlock + */ +static void +syscons_lock_needed(void) +{ + if (sc_lock.flags & SC_NEEDS_UNLOCK) + syscons_lock(); } + /* * Console driver */ @@ -565,16 +587,21 @@ scclose(struct dev_close_args *ap) lwkt_gettoken(&tty_token); if (SC_VTY(dev) != SC_CONSOLECTL) { + /* + * Need to lock here because finish_vt_* functions will + * probably update the status of the scp passed and also + * for consistency with the rest of the calls to finish_vt_* + */ scp = SC_STAT(tp->t_dev); /* were we in the middle of the VT switching process? */ DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit)); + syscons_lock(); if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit)) cons_unavail = FALSE; if (finish_vt_rel(scp, TRUE) == 0) /* force release */ DPRINTF(5, ("reset WAIT_REL, ")); if (finish_vt_acq(scp) == 0) /* force acknowledge */ DPRINTF(5, ("reset WAIT_ACQ, ")); - syscons_lock(); #if 0 /* notyet */ if (scp == &main_console) { scp->pid = 0; @@ -2486,7 +2513,9 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr) } /* go set up the new vty screen */ + sc_lock.flags |= SC_NEEDS_UNLOCK; exchange_scr(sc); + sc_lock.flags &= ~SC_NEEDS_UNLOCK; /* wake up processes waiting for this vty */ wakeup((caddr_t)&sc->cur_scp->smode); @@ -3560,7 +3589,9 @@ save_kbd_state(scr_stat *scp) int state; int error; + syscons_unlock_needed(); error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state); + syscons_lock_needed(); if (error == ENOIOCTL) error = ENODEV; if (error == 0) { @@ -3577,7 +3608,9 @@ update_kbd_state(scr_stat *scp, int new_bits, int mask) int error; if (mask != LOCK_MASK) { + syscons_unlock_needed(); error = kbd_ioctl(scp->sc->kbd, KDGKBSTATE, (caddr_t)&state); + syscons_lock_needed(); if (error == ENOIOCTL) error = ENODEV; if (error) { @@ -3588,7 +3621,9 @@ update_kbd_state(scr_stat *scp, int new_bits, int mask) } else { state = new_bits & LOCK_MASK; } + syscons_unlock_needed(); error = kbd_ioctl(scp->sc->kbd, KDSKBSTATE, (caddr_t)&state); + syscons_lock_needed(); if (error == ENOIOCTL) error = ENODEV; return error; diff --git a/sys/dev/misc/syscons/syscons.h b/sys/dev/misc/syscons/syscons.h index 22bd042..40bc1c1 100644 --- a/sys/dev/misc/syscons/syscons.h +++ b/sys/dev/misc/syscons/syscons.h @@ -36,6 +36,7 @@ #define _DEV_SYSCONS_SYSCONS_H_ #include +#include MALLOC_DECLARE(M_SYSCONS); @@ -140,6 +141,7 @@ MALLOC_DECLARE(M_SYSCONS); #define COL 80 #define ROW 25 #define PCBURST 128 +#define SC_NEEDS_UNLOCK 0x1 #ifndef BELL_DURATION #define BELL_DURATION ((5 * hz + 99) / 100) @@ -171,6 +173,11 @@ struct scr_stat; struct tty; struct dev_ioctl_args; +struct sc_lock { + struct mtx syscons_mtx; + int flags; +}; + typedef struct sc_softc { int unit; /* unit # */ int config; /* configuration flags */