summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-11 18:30:51 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-11 18:30:51 +0000
commitcb538c3cbe26e67bac2b85c75da7259a005d264e (patch)
tree694f7d46090bea822baee9de257c2e4b36c48a69
parent34c122070511a878f53978ec92c6f596fa88cc4d (diff)
serialize usbd_probe_and_attach(); only let one usb device be match'd and
attached at a time; ok kettenis
-rw-r--r--sys/dev/usb/usb_subr.c45
-rw-r--r--sys/dev/usb/usbdi.c7
2 files changed, 37 insertions, 15 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index c30b6b5c70b..d0245d6f44d 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_subr.c,v 1.61 2007/10/06 23:50:55 krw Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.62 2007/10/11 18:30:50 deraadt Exp $ */
/* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -46,6 +46,7 @@
#include <sys/device.h>
#include <sys/selinfo.h>
#include <sys/proc.h>
+#include <sys/rwlock.h>
#include <machine/bus.h>
@@ -833,6 +834,9 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
usbd_status err;
struct device *dv;
usbd_interface_handle *ifaces;
+ extern struct rwlock usbpalock;
+
+ rw_enter_write(&usbpalock);
uaa.device = dev;
uaa.iface = NULL;
@@ -847,15 +851,18 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
uaa.release = UGETW(dd->bcdDevice);
/* First try with device specific drivers. */
- DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
+ DPRINTF(("usbd_probe_and_attach trying device specific drivers\n"));
dv = config_found_sm(parent, &uaa, usbd_print, usbd_submatch);
if (dv) {
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == NULL)
- return (USBD_NOMEM);
+ if (dev->subdevs == NULL) {
+ err = USBD_NOMEM;
+ goto fail;
+ }
dev->subdevs[0] = dv;
dev->subdevs[1] = 0;
- return (USBD_NORMAL_COMPLETION);
+ err = USBD_NORMAL_COMPLETION;
+ goto fail;
}
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
@@ -877,14 +884,16 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
parent->dv_xname, port, addr);
#endif
- return (err);
+ goto fail;
}
nifaces = dev->cdesc->bNumInterface;
uaa.configno = dev->cdesc->bConfigurationValue;
ifaces = malloc(nifaces * sizeof(usbd_interface_handle),
M_USB, M_NOWAIT);
- if (ifaces == NULL)
- return (USBD_NOMEM);
+ if (ifaces == NULL) {
+ err = USBD_NOMEM;
+ goto fail;
+ }
for (i = 0; i < nifaces; i++)
ifaces[i] = &dev->ifaces[i];
uaa.ifaces = ifaces;
@@ -893,7 +902,8 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
dev->subdevs = malloc(len, M_USB, M_NOWAIT | M_ZERO);
if (dev->subdevs == NULL) {
free(ifaces, M_USB);
- return (USBD_NOMEM);
+ err = USBD_NOMEM;
+ goto fail;
}
found = 0;
@@ -912,7 +922,8 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
}
free(ifaces, M_USB);
if (found != 0) {
- return (USBD_NORMAL_COMPLETION);
+ err = USBD_NORMAL_COMPLETION;
+ goto fail;
}
free(dev->subdevs, M_USB);
dev->subdevs = 0;
@@ -932,11 +943,14 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
dv = config_found_sm(parent, &uaa, usbd_print, usbd_submatch);
if (dv != NULL) {
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0)
- return (USBD_NOMEM);
+ if (dev->subdevs == 0) {
+ err = USBD_NOMEM;
+ goto fail;
+ }
dev->subdevs[0] = dv;
dev->subdevs[1] = 0;
- return (USBD_NORMAL_COMPLETION);
+ err = USBD_NORMAL_COMPLETION;
+ goto fail;
}
/*
@@ -945,7 +959,10 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
* fully operational and not harming anyone.
*/
DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
- return (USBD_NORMAL_COMPLETION);
+ err = USBD_NORMAL_COMPLETION;
+fail:
+ rw_exit_write(&usbpalock);
+ return (err);
}
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 4a8e0e2f1df..eed4a617f61 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi.c,v 1.33 2007/06/18 11:37:04 mbalmer Exp $ */
+/* $OpenBSD: usbdi.c,v 1.34 2007/10/11 18:30:50 deraadt Exp $ */
/* $NetBSD: usbdi.c,v 1.103 2002/09/27 15:37:38 provos Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */
@@ -45,6 +45,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <sys/rwlock.h>
#include <machine/bus.h>
@@ -72,9 +73,13 @@ usbd_status usbd_open_pipe_ival(usbd_interface_handle, u_int8_t, u_int8_t,
int usbd_nbuses = 0;
+struct rwlock usbpalock;
+
void
usbd_init(void)
{
+ if (usbd_nbuses == 0)
+ rw_init(&usbpalock, "usbpalock");
usbd_nbuses++;
}