PERFORCE change 166535 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jul 25 09:16:14 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166535
Change 166535 by hselasky at 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);
}
}
More information about the p4-projects
mailing list