Date: Sat, 25 Jul 2009 09:16:12 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 166535 for review Message-ID: <200907250916.n6P9GCQJ073476@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166535 Change 166535 by hselasky@hselasky_laptop001 on 2009/07/25 09:15:52 USB CORE + input: - patch to fix polled mode for UKBD. Add dummy Giant wrappers if polled mode is set. - patch to improve usbd_transfer_poll(). Mostly resolve locking issues and warning printouts at the DDB prompt. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#22 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#161 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#22 (text+ko) ==== @@ -299,6 +299,28 @@ } } +static void +ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) +{ + DPRINTFN(2, "polling\n"); + + while (sc->sc_inputs == 0) { + + usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); + + DELAY(1000); /* delay 1 ms */ + + sc->sc_time_ms++; + + /* support repetition of keys: */ + + ukbd_interrupt(sc); + + if (!wait) + break; + } +} + static int32_t ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) { @@ -311,24 +333,7 @@ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); } if (sc->sc_flags & UKBD_FLAG_POLLING) { - DPRINTFN(2, "polling\n"); - - while (sc->sc_inputs == 0) { - - usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); - - DELAY(1000); /* delay 1 ms */ - - sc->sc_time_ms++; - - /* support repetition of keys: */ - - ukbd_interrupt(sc); - - if (!wait) { - break; - } - } + ukbd_do_poll(sc, wait); } if (sc->sc_inputs == 0) { c = -1; @@ -983,6 +988,14 @@ 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); + } mtx_assert(&Giant, MA_OWNED); KBD_ACTIVATE(kbd); return (0); @@ -992,6 +1005,14 @@ 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); + } mtx_assert(&Giant, MA_OWNED); KBD_DEACTIVATE(kbd); return (0); @@ -1003,14 +1024,26 @@ { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + 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); + } + ukbd_do_poll(sc, 0); + } else { + /* XXX the keyboard layer requires Giant */ + if (!mtx_owned(&Giant)) + return (0); } mtx_assert(&Giant, MA_OWNED); - if (!KBD_IS_ACTIVE(kbd)) { - return (0); - } #ifdef UKBD_EMULATE_ATSCANCODE if (sc->sc_buffered_char[0]) { return (1); @@ -1028,14 +1061,25 @@ { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + 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); } mtx_assert(&Giant, MA_OWNED); - if (!KBD_IS_ACTIVE(kbd)) { - return (0); - } if ((sc->sc_composed_char > 0) && (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { return (1); @@ -1056,9 +1100,22 @@ uint32_t scancode; #endif + if (!KBD_IS_ACTIVE(kbd)) + return (-1); - if (!mtx_owned(&Giant)) { - return -1; /* XXX */ + 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); } mtx_assert(&Giant, MA_OWNED); @@ -1077,9 +1134,9 @@ /* XXX */ usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); - if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) { - return -1; - } + if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) + return (-1); + ++(kbd->kb_count); #ifdef UKBD_EMULATE_ATSCANCODE @@ -1107,8 +1164,23 @@ uint32_t scancode; #endif - if (!mtx_owned(&Giant)) { - return (NOKEY); /* XXX */ + + 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); } mtx_assert(&Giant, MA_OWNED); @@ -1485,7 +1557,12 @@ struct ukbd_softc *sc = kbd->kb_data; if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_poll(kbd, on); + mtx_unlock(&Giant); + return (retval); } mtx_assert(&Giant, MA_OWNED); ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#161 (text+ko) ==== @@ -2858,6 +2858,10 @@ * * The following function gets called from the USB keyboard driver and * UMASS when the system has paniced. + * + * NOTE: It is currently not possible to resume normal operation on + * the USB controller which has been polled, due to clearing of the + * "up_dsleep" and "up_msleep" flags. *------------------------------------------------------------------------*/ void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) @@ -2867,19 +2871,50 @@ 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 */ xfer = ppxfer[n]; if (xfer == NULL) - continue; + continue; /* no USB transfer */ xroot = xfer->xroot; if (xroot == NULL) - continue; + continue; /* no USB root */ udev = xroot->udev; if (udev == NULL) - continue; + continue; /* no USB device */ + if (udev->bus == NULL) + continue; /* no BUS structure */ + if (udev->bus->methods == NULL) + continue; /* no BUS methods */ if (udev->bus->methods->xfer_poll == NULL) - continue; + 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_dsleep = 0; + udev->bus->control_xfer_proc.up_msleep = 0; + udev->bus->explore_proc.up_dsleep = 0; + udev->bus->explore_proc.up_msleep = 0; + udev->bus->giant_callback_proc.up_dsleep = 0; + udev->bus->giant_callback_proc.up_msleep = 0; + udev->bus->non_giant_callback_proc.up_dsleep = 0; + udev->bus->non_giant_callback_proc.up_msleep = 0; /* poll USB hardware */ (udev->bus->methods->xfer_poll) (udev->bus); @@ -2903,6 +2938,14 @@ (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); } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907250916.n6P9GCQJ073476>