Module Name: src
Committed By: nat
Date: Tue Oct 18 20:17:37 UTC 2016
Modified Files:
src/sys/dev/usb: udl.c udl.h
Log Message:
Stop crash when switching vt or leaving X windows.
Improved upon and OK from christos@
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/usb/udl.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/usb/udl.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/udl.c
diff -u src/sys/dev/usb/udl.c:1.16 src/sys/dev/usb/udl.c:1.17
--- src/sys/dev/usb/udl.c:1.16 Mon Oct 17 20:04:48 2016
+++ src/sys/dev/usb/udl.c Tue Oct 18 20:17:37 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $ */
+/* $NetBSD: udl.c,v 1.17 2016/10/18 20:17:37 nat Exp $ */
/*-
* Copyright (c) 2009 FUKAUMI Naoki.
@@ -53,7 +53,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.17 2016/10/18 20:17:37 nat Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -175,6 +175,7 @@ static int udl_set_resolution(struct ud
const struct videomode *);
static const struct videomode *udl_videomode_lookup(const char *);
static void udl_update_thread(void *);
+static inline void udl_startstop(struct udl_softc *, bool);
static inline void
udl_cmd_add_1(struct udl_softc *sc, uint8_t val)
@@ -475,6 +476,7 @@ udl_attach(device_t parent, device_t sel
mutex_init(&sc->sc_thread_mtx, MUTEX_DEFAULT, IPL_NONE);
cv_init(&sc->sc_thread_cv, "udlcv");
sc->sc_dying = false;
+ sc->sc_thread_stop = true;
kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
udl_update_thread, sc, &sc->sc_thread, "udlupd");
}
@@ -511,8 +513,10 @@ udl_detach(device_t self, int flags)
*/
udl_fbmem_free(sc);
+ mutex_enter(&sc->sc_thread_mtx);
sc->sc_dying = true;
cv_broadcast(&sc->sc_thread_cv);
+ mutex_exit(&sc->sc_thread_mtx);
kthread_join(sc->sc_thread);
cv_destroy(&sc->sc_cv);
@@ -571,6 +575,7 @@ udl_ioctl(void *v, void *vs, u_long cmd,
return 0;
switch (mode) {
case WSDISPLAYIO_VIDEO_OFF:
+ udl_startstop(sc, true);
udl_blank(sc, 1);
break;
case WSDISPLAYIO_VIDEO_ON:
@@ -579,7 +584,8 @@ udl_ioctl(void *v, void *vs, u_long cmd,
default:
return EINVAL;
}
- udl_cmd_send_async(sc);
+ if (UDL_CMD_BUFSIZE(sc) > 0)
+ udl_cmd_send_async(sc);
udl_cmdq_flush(sc);
sc->sc_blank = mode;
return 0;
@@ -590,10 +596,12 @@ udl_ioctl(void *v, void *vs, u_long cmd,
return 0;
switch (mode) {
case WSDISPLAYIO_MODE_EMUL:
+ udl_startstop(sc, true);
/* clear screen */
udl_fill_rect(sc, 0, 0, 0, sc->sc_width,
sc->sc_height);
- udl_cmd_send_async(sc);
+ if (UDL_CMD_BUFSIZE(sc) > 0)
+ udl_cmd_send_async(sc);
udl_cmdq_flush(sc);
udl_comp_unload(sc);
break;
@@ -602,6 +610,7 @@ udl_ioctl(void *v, void *vs, u_long cmd,
udl_cmd_send_async(sc);
udl_cmdq_flush(sc);
udl_comp_load(sc);
+ udl_startstop(sc, false);
break;
default:
return EINVAL;
@@ -652,7 +661,8 @@ udl_mmap(void *v, void *vs, off_t off, i
if (udl_fbmem_alloc(sc) != 0)
return -1;
- cv_broadcast(&sc->sc_thread_cv);
+ udl_startstop(sc, false);
+
vaddr = (vaddr_t)sc->sc_fbmem + off;
rv = pmap_extract(pmap_kernel(), vaddr, &paddr);
KASSERT(rv);
@@ -1823,7 +1833,7 @@ udl_update_thread(void *v)
kthread_exit(0);
}
- if (sc->sc_fbmem == NULL)
+ if (sc->sc_thread_stop == true || sc->sc_fbmem == NULL)
goto thread_wait;
#ifdef notyet
@@ -1877,3 +1887,13 @@ thread_wait:
cv_wait(&sc->sc_thread_cv, &sc->sc_thread_mtx);
}
}
+
+static inline void
+udl_startstop(struct udl_softc *sc, bool stop)
+{
+ mutex_enter(&sc->sc_thread_mtx);
+ sc->sc_thread_stop = stop;
+ if (!stop)
+ cv_broadcast(&sc->sc_thread_cv);
+ mutex_exit(&sc->sc_thread_mtx);
+}
Index: src/sys/dev/usb/udl.h
diff -u src/sys/dev/usb/udl.h:1.3 src/sys/dev/usb/udl.h:1.4
--- src/sys/dev/usb/udl.h:1.3 Mon Oct 17 20:04:48 2016
+++ src/sys/dev/usb/udl.h Tue Oct 18 20:17:37 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udl.h,v 1.3 2016/10/17 20:04:48 nat Exp $ */
+/* $NetBSD: udl.h,v 1.4 2016/10/18 20:17:37 nat Exp $ */
/*-
* Copyright (c) 2009 FUKAUMI Naoki.
@@ -119,6 +119,7 @@ struct udl_softc {
kcondvar_t sc_thread_cv;
kmutex_t sc_thread_mtx;
bool sc_dying;
+ bool sc_thread_stop;
lwp_t *sc_thread;
kcondvar_t sc_cv;