PERFORCE change 173914 for review

Hans Petter Selasky hselasky at FreeBSD.org
Fri Jan 29 17:40:38 UTC 2010


http://p4web.freebsd.org/chv.cgi?CH=173914

Change 173914 by hselasky at hselasky_laptop001 on 2010/01/29 17:40:27

	
	USB input:
		- improve kernel polling support.
	
	PR:		usb/143286, kern/141011

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#43 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#43 (text+ko) ====

@@ -151,6 +151,7 @@
 	struct ukbd_data sc_ndata;
 	struct ukbd_data sc_odata;
 
+	struct thread *sc_poll_thread;
 	struct usb_device *sc_udev;
 	struct usb_interface *sc_iface;
 	struct usb_xfer *sc_xfer[UKBD_N_TRANSFER];
@@ -284,6 +285,7 @@
 static int	ukbd_disable(keyboard_t *);
 static void	ukbd_interrupt(struct ukbd_softc *);
 static int	ukbd_is_polling(struct ukbd_softc *);
+static int	ukbd_polls_other_thread(struct ukbd_softc *);
 static void	ukbd_event_keyinput(struct ukbd_softc *);
 
 static device_probe_t ukbd_probe;
@@ -335,9 +337,19 @@
 {
 	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) {
-		/* make sure the USB code gets a chance to run */
-		pause("UKBD", 1);
+		while (sc->sc_inputs == 0) {
+			/* make sure the USB code gets a chance to run */
+			pause("UKBD", 1);
+
+			/* check if we should wait */
+			if (!wait)
+				break;
+		}
 		return;		/* Only poll if KDB is active */
 	}
 
@@ -373,9 +385,13 @@
 		/* start transfer, if not already started */
 		usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
 	}
-	if (sc->sc_flags & UKBD_FLAG_POLLING) {
+
+	if (ukbd_polls_other_thread(sc))
+		return (-1);
+
+	if (sc->sc_flags & UKBD_FLAG_POLLING)
 		ukbd_do_poll(sc, wait);
-	}
+
 	if (sc->sc_inputs == 0) {
 		c = -1;
 	} else {
@@ -400,9 +416,9 @@
 	uint8_t i;
 	uint8_t j;
 
-	if (sc->sc_ndata.keycode[0] == KEY_ERROR) {
-		goto done;
-	}
+	if (sc->sc_ndata.keycode[0] == KEY_ERROR)
+		return;
+
 	n_mod = sc->sc_ndata.modifiers;
 	o_mod = sc->sc_odata.modifiers;
 	if (n_mod != o_mod) {
@@ -475,17 +491,9 @@
 
 	sc->sc_odata = sc->sc_ndata;
 
-	bcopy(sc->sc_ntime, sc->sc_otime, sizeof(sc->sc_otime));
+	memcpy(sc->sc_otime, sc->sc_ntime, sizeof(sc->sc_otime));
 
-	if (ukbd_is_polling(sc))
-		goto done;
-	if (sc->sc_inputs == 0)
-		goto done;
-
 	ukbd_event_keyinput(sc);
-
-done:
-	return;
 }
 
 static void
@@ -493,6 +501,12 @@
 {
 	int c;
 
+	if (ukbd_is_polling(sc))
+		return;
+
+	if (sc->sc_inputs == 0)
+		return;
+
 	if (KBD_IS_ACTIVE(&sc->sc_kbd) &&
 	    KBD_IS_BUSY(&sc->sc_kbd)) {
 		/* let the callback function process the input */
@@ -518,8 +532,7 @@
 	ukbd_interrupt(sc);
 
 	/* Make sure any leftover key events gets read out */
-	if (ukbd_is_polling(sc) == 0)
-		ukbd_event_keyinput(sc);
+	ukbd_event_keyinput(sc);
 
 	if (ukbd_any_key_pressed(sc) || (sc->sc_inputs != 0)) {
 		ukbd_start_timer(sc);
@@ -1102,13 +1115,19 @@
 			mtx_unlock(&Giant);
 			return (retval);
 		}
-		ukbd_do_poll(sc, 0);
 	} 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);
+
+	if (sc->sc_flags & UKBD_FLAG_POLLING)
+		ukbd_do_poll(sc, 0);
+
 #ifdef UKBD_EMULATE_ATSCANCODE
 	if (sc->sc_buffered_char[0]) {
 		return (1);
@@ -1144,6 +1163,10 @@
 			return (0);
 	}
 
+	/* check if key belongs to this thread */
+	if (ukbd_polls_other_thread(sc))
+		return (0);
+
 	if ((sc->sc_composed_char > 0) &&
 	    (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) {
 		return (1);
@@ -1182,6 +1205,10 @@
 			return (-1);
 	}
 
+	/* check if key belongs to this thread */
+	if (ukbd_polls_other_thread(sc))
+		return (-1);
+
 #ifdef UKBD_EMULATE_ATSCANCODE
 	if (sc->sc_buffered_char[0]) {
 		scancode = sc->sc_buffered_char[0];
@@ -1246,6 +1273,10 @@
 			return (NOKEY);
 	}
 
+	/* check if key belongs to this thread */
+	if (ukbd_polls_other_thread(sc))
+		return (NOKEY);
+
 next_code:
 
 	/* do we have a composed char to return ? */
@@ -1629,11 +1660,8 @@
 {
 	int delta;
 
-	if (sc->sc_flags & UKBD_FLAG_POLLING) {
-		sc->sc_poll_tick_last = ticks;
-		sc->sc_poll_detected = 1;
+	if (sc->sc_flags & UKBD_FLAG_POLLING)
 		return (1);	/* polling */
-	}
 
 	delta = ticks - sc->sc_poll_tick_last;
 	if ((delta < 0) || (delta >= hz)) {
@@ -1645,6 +1673,13 @@
 }
 
 static int
+ukbd_polls_other_thread(struct ukbd_softc *sc)
+{
+	return (ukbd_is_polling(sc) &&
+	    (sc->sc_poll_thread != curthread));
+}
+
+static int
 ukbd_poll(keyboard_t *kbd, int on)
 {
 	struct ukbd_softc *sc = kbd->kb_data;
@@ -1660,7 +1695,7 @@
 
 	if (on) {
 		sc->sc_flags |= UKBD_FLAG_POLLING;
-		ukbd_is_polling(sc);	/* update state */
+		sc->sc_poll_thread = curthread;
 	} else {
 		sc->sc_flags &= ~UKBD_FLAG_POLLING;
 		ukbd_start_timer(sc);	/* start timer */


More information about the p4-projects mailing list