Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/usb/udl.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/usb/udl.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.16 retrieving revision 1.17 diff -u -p -r1.16 -r1.17 --- src/sys/dev/usb/udl.c 2016/10/17 20:04:48 1.16 +++ src/sys/dev/usb/udl.c 2016/10/18 20:17:37 1.17 @@ -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 -__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 #include @@ -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); +}