commit d17028aa537d65d74b5250f16c98571e75f8a7c4 Author: Andriy Gapon Date: Thu Sep 1 16:13:10 2011 +0300 additional changes to support stopped scheduler after panic - syscons: lock Giant around code that polls the keyboard - usb_transfer: adapt for SCHEDULER_STOPPED() - ukbd: simplify locking in ukbd and make it work with SCHEDULER_STOPPED diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 69d628e..d3e0de9 100644 --- sys/dev/syscons/syscons.c +++ sys/dev/syscons/syscons.c @@ -1664,6 +1664,7 @@ sc_cngetc(struct consdev *cd) const u_char *p; int cur_mode; int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ + int locked; int c; /* assert(sc_console != NULL) */ @@ -1697,10 +1698,19 @@ sc_cngetc(struct consdev *cd) scp->kbd_mode = K_XLATE; (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + locked = 0; + if (!kdb_active) { + mtx_lock(&Giant); + locked = 1; + } + kbdd_poll(scp->sc->kbd, TRUE); c = scgetc(scp->sc, SCGETC_CN | SCGETC_NONBLOCK); kbdd_poll(scp->sc->kbd, FALSE); + if (locked) + mtx_unlock(&Giant); + scp->kbd_mode = cur_mode; (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); kbdd_disable(scp->sc->kbd); diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index bf3ecd7..7611a25 100644 --- sys/dev/usb/input/ukbd.c +++ sys/dev/usb/input/ukbd.c @@ -370,7 +370,6 @@ ukbd_start_timer(struct ukbd_softc *sc) static void ukbd_put_key(struct ukbd_softc *sc, uint32_t key) { - mtx_assert(&Giant, MA_OWNED); DPRINTF("0x%02x (%d) %s\n", key, key, (key & KEY_RELEASE) ? "released" : "pressed"); @@ -417,13 +416,14 @@ ukbd_yield(void) static void ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) { + DPRINTFN(2, "polling\n"); /* update stats about last polling event */ sc->sc_poll_tick_last = ticks; sc->sc_poll_detected = 1; - if (kdb_active == 0) { + if (!kdb_active && !SCHEDULER_STOPPED()) { while (sc->sc_inputs == 0) { /* give USB threads a chance to run */ @@ -462,8 +462,6 @@ ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) { int32_t c; - mtx_assert(&Giant, MA_OWNED); - if (sc->sc_inputs == 0) { /* start transfer, if not already started */ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); @@ -608,8 +606,6 @@ ukbd_timeout(void *arg) { struct ukbd_softc *sc = arg; - mtx_assert(&Giant, MA_OWNED); - sc->sc_time_ms += 25; /* milliseconds */ ukbd_interrupt(sc); @@ -1241,14 +1237,10 @@ ukbd_attach(device_t dev) /* ignore if SETIDLE fails, hence it is not crucial */ usbd_req_set_idle(sc->sc_udev, NULL, sc->sc_iface_index, 0, 0); - mtx_lock(&Giant); - ukbd_ioctl(kbd, KDSETLED, (caddr_t)&sc->sc_state); KBD_INIT_DONE(kbd); - mtx_unlock(&Giant); - if (kbd_register(kbd) < 0) { goto detach; } @@ -1266,15 +1258,10 @@ ukbd_attach(device_t dev) if (bootverbose) { genkbd_diag(kbd, bootverbose); } - /* lock keyboard mutex */ - - mtx_lock(&Giant); /* start the keyboard */ - usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); - mtx_unlock(&Giant); return (0); /* success */ detach: @@ -1290,8 +1277,6 @@ ukbd_detach(device_t dev) DPRINTF("\n"); - mtx_lock(&Giant); - sc->sc_flags |= UKBD_FLAG_GONE; usb_callout_stop(&sc->sc_callout); @@ -1318,8 +1303,6 @@ ukbd_detach(device_t dev) } sc->sc_kbd.kb_flags = 0; - mtx_unlock(&Giant); - usbd_transfer_unsetup(sc->sc_xfer, UKBD_N_TRANSFER); usb_callout_drain(&sc->sc_callout); @@ -1335,12 +1318,8 @@ ukbd_resume(device_t dev) { struct ukbd_softc *sc = device_get_softc(dev); - mtx_lock(&Giant); - ukbd_clear_state(&sc->sc_kbd); - mtx_unlock(&Giant); - return (0); } @@ -1400,14 +1379,7 @@ ukbd_lock(keyboard_t *kbd, int lock) static int ukbd_enable(keyboard_t *kbd) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_enable(kbd); - mtx_unlock(&Giant); - return (retval); - } + KBD_ACTIVATE(kbd); return (0); } @@ -1416,14 +1388,7 @@ ukbd_enable(keyboard_t *kbd) static int ukbd_disable(keyboard_t *kbd) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_disable(kbd); - mtx_unlock(&Giant); - return (retval); - } + KBD_DEACTIVATE(kbd); return (0); } @@ -1437,21 +1402,6 @@ ukbd_check(keyboard_t *kbd) if (!KBD_IS_ACTIVE(kbd)) return (0); - if (sc->sc_flags & UKBD_FLAG_POLLING) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_check(kbd); - mtx_unlock(&Giant); - return (retval); - } - } else { - /* XXX the keyboard layer requires Giant */ - if (!mtx_owned(&Giant)) - return (0); - } - /* check if key belongs to this thread */ if (ukbd_polls_other_thread(sc)) return (0); @@ -1479,21 +1429,6 @@ ukbd_check_char(keyboard_t *kbd) if (!KBD_IS_ACTIVE(kbd)) return (0); - if (sc->sc_flags & UKBD_FLAG_POLLING) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_check_char(kbd); - mtx_unlock(&Giant); - return (retval); - } - } else { - /* XXX the keyboard layer requires Giant */ - if (!mtx_owned(&Giant)) - return (0); - } - /* check if key belongs to this thread */ if (ukbd_polls_other_thread(sc)) return (0); @@ -1521,21 +1456,6 @@ ukbd_read(keyboard_t *kbd, int wait) if (!KBD_IS_ACTIVE(kbd)) return (-1); - if (sc->sc_flags & UKBD_FLAG_POLLING) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_read(kbd, wait); - mtx_unlock(&Giant); - return (retval); - } - } else { - /* XXX the keyboard layer requires Giant */ - if (!mtx_owned(&Giant)) - return (-1); - } - /* check if key belongs to this thread */ if (ukbd_polls_other_thread(sc)) return (-1); @@ -1589,21 +1509,6 @@ ukbd_read_char(keyboard_t *kbd, int wait) if (!KBD_IS_ACTIVE(kbd)) return (NOKEY); - if (sc->sc_flags & UKBD_FLAG_POLLING) { - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_read_char(kbd, wait); - mtx_unlock(&Giant); - return (retval); - } - } else { - /* XXX the keyboard layer requires Giant */ - if (!mtx_owned(&Giant)) - return (NOKEY); - } - /* check if key belongs to this thread */ if (ukbd_polls_other_thread(sc)) return (NOKEY); @@ -1788,33 +1693,11 @@ ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) { struct ukbd_softc *sc = kbd->kb_data; int i; - #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) int ival; #endif - if (!mtx_owned(&Giant)) { - /* - * XXX big problem: If scroll lock is pressed and "printf()" - * is called, the CPU will get here, to un-scroll lock the - * keyboard. But if "printf()" acquires the "Giant" lock, - * there will be a locking order reversal problem, so the - * keyboard system must get out of "Giant" first, before the - * CPU can proceed here ... - */ - switch (cmd) { - case KDGKBMODE: - case KDSKBMODE: - /* workaround for Geli */ - mtx_lock(&Giant); - i = ukbd_ioctl(kbd, cmd, arg); - mtx_unlock(&Giant); - return (i); - default: - return (EINVAL); - } - } switch (cmd) { case KDGKBMODE: /* get keyboard mode */ @@ -1949,14 +1832,6 @@ ukbd_clear_state(keyboard_t *kbd) { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - mtx_lock(&Giant); - ukbd_clear_state(kbd); - mtx_unlock(&Giant); - return; - } - sc->sc_flags &= ~(UKBD_FLAG_COMPOSE | UKBD_FLAG_POLLING); sc->sc_state &= LOCK_MASK; /* preserve locking key state */ sc->sc_accents = 0; @@ -2014,15 +1889,6 @@ ukbd_poll(keyboard_t *kbd, int on) { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - /* XXX cludge */ - int retval; - mtx_lock(&Giant); - retval = ukbd_poll(kbd, on); - mtx_unlock(&Giant); - return (retval); - } - if (on) { sc->sc_flags |= UKBD_FLAG_POLLING; sc->sc_poll_thread = curthread; diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index d4c2408..ef50dc4 100644 --- sys/dev/usb/usb_transfer.c +++ sys/dev/usb/usb_transfer.c @@ -2150,7 +2150,7 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq) struct usb_xfer_root *info = xfer->xroot; USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED); - if (!mtx_owned(info->xfer_mtx)) { + if (!SCHEDULER_STOPPED() && !mtx_owned(info->xfer_mtx)) { /* * Cases that end up here: * @@ -3094,8 +3094,6 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) struct usb_device *udev; struct usb_proc_msg *pm; uint16_t n; - uint16_t drop_bus; - uint16_t drop_xfer; for (n = 0; n != max; n++) { /* Extra checks to avoid panic */ @@ -3115,20 +3113,6 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) if (udev->bus->methods->xfer_poll == NULL) continue; /* no poll method */ - /* make sure that the BUS mutex is not locked */ - drop_bus = 0; - while (mtx_owned(&xroot->udev->bus->bus_mtx)) { - mtx_unlock(&xroot->udev->bus->bus_mtx); - drop_bus++; - } - - /* make sure that the transfer mutex is not locked */ - drop_xfer = 0; - while (mtx_owned(xroot->xfer_mtx)) { - mtx_unlock(xroot->xfer_mtx); - drop_xfer++; - } - /* Make sure cv_signal() and cv_broadcast() is not called */ udev->bus->control_xfer_proc.up_msleep = 0; udev->bus->explore_proc.up_msleep = 0; @@ -3157,14 +3141,6 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) (pm->pm_callback) (pm); USB_BUS_UNLOCK(xroot->bus); - - /* restore transfer mutex */ - while (drop_xfer--) - mtx_lock(xroot->xfer_mtx); - - /* restore BUS mutex */ - while (drop_bus--) - mtx_lock(&xroot->udev->bus->bus_mtx); } }