Module Name:    src
Committed By:   mrg
Date:           Mon Feb 20 03:27:07 UTC 2012

Modified Files:
        src/sys/dev/usb [jmcneill-usbmp]: usb.c

Log Message:
convert usb event code to using a mutex and condvar.


To generate a diff of this commit:
cvs rdiff -u -r1.125.6.6 -r1.125.6.7 src/sys/dev/usb/usb.c

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/usb.c
diff -u src/sys/dev/usb/usb.c:1.125.6.6 src/sys/dev/usb/usb.c:1.125.6.7
--- src/sys/dev/usb/usb.c:1.125.6.6	Mon Feb 20 02:12:24 2012
+++ src/sys/dev/usb/usb.c	Mon Feb 20 03:27:07 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb.c,v 1.125.6.6 2012/02/20 02:12:24 mrg Exp $	*/
+/*	$NetBSD: usb.c,v 1.125.6.7 2012/02/20 03:27:07 mrg Exp $	*/
 
 /*
  * Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.6 2012/02/20 02:12:24 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.125.6.7 2012/02/20 03:27:07 mrg Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_usb.h"
@@ -57,19 +57,19 @@ __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.12
 #include <sys/signalvar.h>
 #include <sys/intr.h>
 #include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/once.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
 #include <dev/usb/usb_verbose.h>
+#include <dev/usb/usb_quirks.h>
 
 #define USB_DEV_MINOR 255
 
-#include <sys/bus.h>
-
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usb_quirks.h>
-
 #ifdef USB_DEBUG
 #define DPRINTF(x)	if (usbdebug) printf x
 #define DPRINTFN(n,x)	if (usbdebug>(n)) printf x
@@ -135,6 +135,8 @@ Static SIMPLEQ_HEAD(, usb_event_q) usb_e
 	SIMPLEQ_HEAD_INITIALIZER(usb_events);
 Static int usb_nevents = 0;
 Static struct selinfo usb_selevent;
+Static kmutex_t usb_event_lock;
+Static kcondvar_t usb_event_cv;
 Static proc_t *usb_async_proc;  /* process that wants USB SIGIO */
 Static void *usb_async_sih;
 Static int usb_dev_open = 0;
@@ -156,6 +158,7 @@ static void usb_attach(device_t, device_
 static int usb_detach(device_t, int);
 static int usb_activate(device_t, enum devact);
 static void usb_childdet(device_t, device_t);
+static int usb_once_init(void);
 static void usb_doattach(device_t);
 
 extern struct cfdriver usb_cd;
@@ -174,6 +177,7 @@ usb_match(device_t parent, cfdata_t matc
 void
 usb_attach(device_t parent, device_t self, void *aux)
 {
+	static ONCE_DECL(init_control);
 	struct usb_softc *sc = device_private(self);
 	int usbrev;
 
@@ -194,13 +198,23 @@ usb_attach(device_t parent, device_t sel
 	}
 	aprint_normal("\n");
 
+	RUN_ONCE(&init_control, usb_once_init);
 	config_interrupts(self, usb_doattach);
 }
 
+static int
+usb_once_init(void)
+{
+
+	selinit(&usb_selevent);
+	mutex_init(&usb_event_lock, MUTEX_DEFAULT, IPL_NONE);
+	cv_init(&usb_event_cv, "usbrea");
+	return 0;
+}
+
 static void
 usb_doattach(device_t self)
 {
-	static bool usb_selevent_init;	/* XXX */
 	struct usb_softc *sc = device_private(self);
 	usbd_device_handle dev;
 	usbd_status err;
@@ -208,10 +222,6 @@ usb_doattach(device_t self)
 	struct usb_event *ue;
 	bool mpsafe = sc->sc_bus->methods->get_locks ? true : false;
 
-	if (!usb_selevent_init) {
-		selinit(&usb_selevent);
-		usb_selevent_init = true;
-	}
 	DPRINTF(("usbd_doattach\n"));
 
 	sc->sc_bus->usbctl = self;
@@ -485,7 +495,7 @@ usbread(dev_t dev, struct uio *uio, int 
 #ifdef COMPAT_30
 	struct usb_event_old *ueo = NULL;	/* XXXGCC */
 #endif
-	int s, error, n, useold;
+	int error, n, useold;
 
 	if (minor(dev) != USB_DEV_MINOR)
 		return (ENXIO);
@@ -507,7 +517,7 @@ usbread(dev_t dev, struct uio *uio, int 
 	}
 
 	error = 0;
-	s = splusb();
+	mutex_enter(&usb_event_lock);
 	for (;;) {
 		n = usb_get_next_event(ue);
 		if (n != 0)
@@ -516,11 +526,11 @@ usbread(dev_t dev, struct uio *uio, int 
 			error = EWOULDBLOCK;
 			break;
 		}
-		error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
+		error = cv_wait_sig(&usb_event_cv, &usb_event_lock);
 		if (error)
 			break;
 	}
-	splx(s);
+	mutex_exit(&usb_event_lock);
 	if (!error) {
 #ifdef COMPAT_30
 		if (useold) { /* copy fields to old struct */
@@ -721,18 +731,18 @@ usbioctl(dev_t devt, u_long cmd, void *d
 int
 usbpoll(dev_t dev, int events, struct lwp *l)
 {
-	int revents, mask, s;
+	int revents, mask;
 
 	if (minor(dev) == USB_DEV_MINOR) {
 		revents = 0;
 		mask = POLLIN | POLLRDNORM;
 
-		s = splusb();
+		mutex_enter(&usb_event_lock);
 		if (events & mask && usb_nevents > 0)
 			revents |= events & mask;
 		if (revents == 0 && events & mask)
 			selrecord(l, &usb_selevent);
-		splx(s);
+		mutex_exit(&usb_event_lock);
 
 		return (revents);
 	} else {
@@ -743,11 +753,10 @@ usbpoll(dev_t dev, int events, struct lw
 static void
 filt_usbrdetach(struct knote *kn)
 {
-	int s;
 
-	s = splusb();
+	mutex_enter(&usb_event_lock);
 	SLIST_REMOVE(&usb_selevent.sel_klist, kn, knote, kn_selnext);
-	splx(s);
+	mutex_exit(&usb_event_lock);
 }
 
 static int
@@ -768,7 +777,6 @@ int
 usbkqfilter(dev_t dev, struct knote *kn)
 {
 	struct klist *klist;
-	int s;
 
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
@@ -784,9 +792,9 @@ usbkqfilter(dev_t dev, struct knote *kn)
 
 	kn->kn_hook = NULL;
 
-	s = splusb();
+	mutex_enter(&usb_event_lock);
 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
-	splx(s);
+	mutex_exit(&usb_event_lock);
 
 	return (0);
 }
@@ -847,12 +855,14 @@ usb_needs_reattach(usbd_device_handle de
 		wakeup(&dev->bus->needs_explore);
 }
 
-/* Called at splusb() */
+/* Called at with usb_event_lock held. */
 int
 usb_get_next_event(struct usb_event *ue)
 {
 	struct usb_event_q *ueq;
 
+	KASSERT(mutex_owned(&usb_event_lock));
+
 	if (usb_nevents <= 0)
 		return (0);
 	ueq = SIMPLEQ_FIRST(&usb_events);
@@ -909,30 +919,29 @@ usb_add_event(int type, struct usb_event
 {
 	struct usb_event_q *ueq;
 	struct timeval thetime;
-	int s;
 
 	microtime(&thetime);
-	/* Don't want to wait here inside splusb() */
+	/* Don't want to wait here with usb_event_lock held */
 	ueq = (struct usb_event_q *)(void *)uep;
 	ueq->ue = *uep;
 	ueq->ue.ue_type = type;
 	TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
 
-	s = splusb();
+	mutex_enter(&usb_event_lock);
 	if (++usb_nevents >= USB_MAX_EVENTS) {
 		/* Too many queued events, drop an old one. */
 		DPRINTFN(-1,("usb: event dropped\n"));
 		(void)usb_get_next_event(0);
 	}
 	SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
-	wakeup(&usb_events);
+	cv_signal(&usb_event_cv);
 	selnotify(&usb_selevent, 0, 0);
 	if (usb_async_proc != NULL) {
 		kpreempt_disable();
 		softint_schedule(usb_async_sih);
 		kpreempt_enable();
 	}
-	splx(s);
+	mutex_exit(&usb_event_lock);
 }
 
 Static void

Reply via email to