summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2011-07-13 21:07:50 +0000
committerhselasky <hselasky@FreeBSD.org>2011-07-13 21:07:50 +0000
commitced2dc53dd978014d70cc329aa2e8a1876204390 (patch)
tree0f3c81078a5f535c732588321fa825ad8898e883 /sys/dev
parente3d33b853d78d9c9665b164f2343f53be9338b44 (diff)
downloadFreeBSD-src-ced2dc53dd978014d70cc329aa2e8a1876204390.zip
FreeBSD-src-ced2dc53dd978014d70cc329aa2e8a1876204390.tar.gz
Fix for dump after shutdown with USB keyboard plugged in. It appears that the
system timer is stopped during shutdown and that the pause() statement in ukbd causes infinite hang in this regard. The fix is to use mi_switch() instead of pause() to do the required task switch to ensure that the required USB processes get executed. Reported by: Mike_Karels@mcafee.com MFC after: 1 week
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/input/ukbd.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index aa68f7e..1ad3bd5 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
#include <sys/kdb.h>
#include <dev/usb/usb.h>
@@ -386,6 +388,33 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t key)
}
static void
+ukbd_yield(void)
+{
+ struct thread *td = curthread;
+ uint32_t old_prio;
+
+ DROP_GIANT();
+
+ thread_lock(td);
+
+ /* get current priority */
+ old_prio = td->td_base_pri;
+
+ /* set new priority */
+ sched_prio(td, td->td_user_pri);
+
+ /* cause a task switch */
+ mi_switch(SW_INVOL | SWT_RELINQUISH, NULL);
+
+ /* restore priority */
+ sched_prio(td, old_prio);
+
+ thread_unlock(td);
+
+ PICKUP_GIANT();
+}
+
+static void
ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait)
{
DPRINTFN(2, "polling\n");
@@ -396,8 +425,9 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait)
if (kdb_active == 0) {
while (sc->sc_inputs == 0) {
- /* make sure the USB code gets a chance to run */
- pause("UKBD", 1);
+
+ /* give USB threads a chance to run */
+ ukbd_yield();
/* check if we should wait */
if (!wait)
OpenPOWER on IntegriCloud