diff options
author | peter <peter@FreeBSD.org> | 2001-06-06 22:00:03 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2001-06-06 22:00:03 +0000 |
commit | 736ceb47561d46a525c9e59e2544571a4271b191 (patch) | |
tree | 7023697cf4322aed9e2442c02e9a180c340d9a26 /sys/dev/usb/usb.c | |
parent | 99368be5028bdd9b799bf082e93e46d97946f70c (diff) | |
download | FreeBSD-src-736ceb47561d46a525c9e59e2544571a4271b191.zip FreeBSD-src-736ceb47561d46a525c9e59e2544571a4271b191.tar.gz |
Activate the kthread mechanism for doing usb bus discovery. This means
that device add/remove will work without usbd running. usbd is still
used for execing stuff, but that is all now. Ideally it could be replaced
by a devd some day. Until now, usbd had to be running so that the
USB_DISCOVER ioctl could be called to walk the tree when an attachment
status change was noticed.
Among the changes:
- when a detach happens, remove any pending 'attach' messages or the system
suffers from whiplash from exec moused / kill moused loops if you do lots
of attach/detach and later start usbd.
- tweaks related to kthread differences
- disable the select handler for the old interface (never return success).
I have not removed it yet or old usbd's will abort. That can get removed
later once usbd is cleaned up and things have stabilized for a few weeks.
- get Giant in the kthread.
- a couple of minor potential bug fixes (usb_nevents vs malloc failure etc)
Pre-approved by: n_hibma (ages and ages ago)
Diffstat (limited to 'sys/dev/usb/usb.c')
-rw-r--r-- | sys/dev/usb/usb.c | 92 |
1 files changed, 46 insertions, 46 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index c99f8bf..7979161 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -50,10 +50,11 @@ #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mutex.h> +#include <sys/kthread.h> #if defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/device.h> -#include <sys/kthread.h> #elif defined(__FreeBSD__) +#include <sys/unistd.h> #include <sys/module.h> #include <sys/bus.h> #include <sys/filio.h> @@ -116,12 +117,7 @@ struct usb_softc { usbd_bus_handle sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ -#if defined(__FreeBSD__) - /* This part should be deleted when kthreads is available */ - struct selinfo sc_consel; /* waiting for connect change */ -#else struct proc *sc_event_thread; -#endif char sc_dying; }; @@ -153,18 +149,16 @@ struct cdevsw usb_cdevsw = { #endif Static usbd_status usb_discover(struct usb_softc *); -#if defined(__NetBSD__) || defined(__OpenBSD__) Static void usb_create_event_thread(void *); Static void usb_event_thread(void *); -#endif #define USB_MAX_EVENTS 50 struct usb_event_q { struct usb_event ue; - SIMPLEQ_ENTRY(usb_event_q) next; + TAILQ_ENTRY(usb_event_q) next; }; -Static SIMPLEQ_HEAD(, usb_event_q) usb_events = - SIMPLEQ_HEAD_INITIALIZER(usb_events); +Static TAILQ_HEAD(, usb_event_q) usb_events = + TAILQ_HEAD_INITIALIZER(usb_events); Static int usb_nevents = 0; Static struct selinfo usb_selevent; Static struct proc *usb_async_proc; /* process who wants USB SIGIO */ @@ -257,10 +251,14 @@ USB_ATTACH(usb) sc->sc_dying = 1; } +#if defined(__NetBSD__) || defined(__OpenBSD__) kthread_create(usb_create_event_thread, sc); +#endif #if defined(__FreeBSD__) + usb_create_event_thread(sc); /* The per controller devices (used for usb_discover) */ + /* XXX This is redundant now, but old usbd's will want it */ make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, 0660, "usb%d", device_get_unit(self)); if (!global_init_done) { @@ -274,7 +272,6 @@ USB_ATTACH(usb) USB_ATTACH_SUCCESS_RETURN; } -#if defined(__NetBSD__) || defined(__OpenBSD__) void usb_create_event_thread(arg) void *arg; @@ -282,9 +279,9 @@ usb_create_event_thread(arg) struct usb_softc *sc = arg; if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread, - "%s", sc->sc_dev.dv_xname)) { + "%s", USBDEVNAME(sc->sc_dev))) { printf("%s: unable to create event thread for\n", - sc->sc_dev.dv_xname); + USBDEVNAME(sc->sc_dev)); panic("usb_create_event_thread"); } } @@ -294,6 +291,11 @@ usb_event_thread(arg) void *arg; { struct usb_softc *sc = arg; + int to; + +#ifdef __FreeBSD__ + mtx_lock(&Giant); +#endif DPRINTF(("usb_event_thread: start\n")); @@ -302,12 +304,12 @@ usb_event_thread(arg) if (usb_noexplore < 2) #endif usb_discover(sc); - (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", + to = hz * 60; #ifdef USB_DEBUG - usb_noexplore ? 0 : + if (usb_noexplore) + to = 0; #endif - hz*60 - ); + (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", to); DPRINTFN(2,("usb_event_thread: woke up\n")); } sc->sc_event_thread = 0; @@ -319,6 +321,7 @@ usb_event_thread(arg) kthread_exit(0); } +#if defined(__NetBSD__) || defined(__OpenBSD__) int usbctlprint(aux, pnp) void *aux; @@ -446,9 +449,8 @@ usbioctl(devt, cmd, data, flag, p) switch (cmd) { #if defined(__FreeBSD__) - /* This part should be deleted when kthreads is available */ + /* This part should be deleted */ case USB_DISCOVER: - usb_discover(sc); break; #endif #ifdef USB_DEBUG @@ -567,22 +569,7 @@ usbpoll(dev, events, p) return (revents); } else { #if defined(__FreeBSD__) - /* This part should be deleted when kthreads is available */ - struct usb_softc *sc; - - USB_GET_SC(usb, unit, sc); - - revents = 0; - mask = POLLOUT | POLLRDNORM; - - s = splusb(); - if ((events & mask) && sc->sc_bus->needs_explore) - revents |= events & mask; - if (revents == 0 && (events & mask)) - selrecord(p, &sc->sc_consel); - splx(s); - - return (revents); + return (0); /* select/poll never wakes up - back compat */ #else return (ENXIO); #endif @@ -595,7 +582,7 @@ usb_discover(sc) struct usb_softc *sc; { #if defined(__FreeBSD__) - /* The splxxx parts should be deleted when kthreads is available */ + /* splxxx should be changed to mutexes for preemption safety some day */ int s; #endif @@ -629,10 +616,6 @@ usb_needs_explore(bus) usbd_bus_handle bus; { bus->needs_explore = 1; -#if defined(__FreeBSD__) - /* This part should be deleted when kthreads is available */ - selwakeup(&bus->usbctl->sc_consel); -#endif wakeup(&bus->needs_explore); } @@ -645,9 +628,14 @@ usb_get_next_event(ue) if (usb_nevents <= 0) return (0); - ueq = SIMPLEQ_FIRST(&usb_events); + ueq = TAILQ_FIRST(&usb_events); + if (ueq == NULL) { + printf("usb: usb_nevents got out of sync! %d\n", usb_nevents); + usb_nevents = 0; + return (0); + } *ue = ueq->ue; - SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next); + TAILQ_REMOVE(&usb_events, ueq, next); free(ueq, M_USBDEV); usb_nevents--; return (1); @@ -658,13 +646,24 @@ usbd_add_event(type, dev) int type; usbd_device_handle dev; { - struct usb_event_q *ueq; + struct usb_event_q *ueq, *ueq_next; struct usb_event ue; struct timeval thetime; int s; s = splusb(); - if (++usb_nevents >= USB_MAX_EVENTS) { + if (type == USB_EVENT_DETACH) { + for (ueq = TAILQ_FIRST(&usb_events); ueq; ueq = ueq_next) { + ueq_next = TAILQ_NEXT(ueq, next); + if (ueq->ue.ue_cookie.cookie == dev->cookie.cookie) { + TAILQ_REMOVE(&usb_events, ueq, next); + free(ueq, M_USBDEV); + usb_nevents--; + ueq_next = TAILQ_FIRST(&usb_events); + } + } + } + if (usb_nevents >= USB_MAX_EVENTS) { /* Too many queued events, drop an old one. */ DPRINTF(("usb: event dropped\n")); (void)usb_get_next_event(&ue); @@ -681,7 +680,8 @@ usbd_add_event(type, dev) usbd_fill_deviceinfo(dev, &ueq->ue.ue_device); microtime(&thetime); TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); - SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); + TAILQ_INSERT_TAIL(&usb_events, ueq, next); + usb_nevents++; wakeup(&usb_events); selwakeup(&usb_selevent); if (usb_async_proc != NULL) { |