summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usb_subr.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2004-08-14 22:10:26 +0000
committerimp <imp@FreeBSD.org>2004-08-14 22:10:26 +0000
commitda6b7d8015bfe072fdecf22c4958f40e135d3c2b (patch)
tree9b99e9bea5a7c62b7a26bf54ee02ab0537c960ee /sys/dev/usb/usb_subr.c
parentbce29358a4ba1d2f5f059296d3e2d2d6ff05ce13 (diff)
downloadFreeBSD-src-da6b7d8015bfe072fdecf22c4958f40e135d3c2b.zip
FreeBSD-src-da6b7d8015bfe072fdecf22c4958f40e135d3c2b.tar.gz
Next step in making usb more newbus:
o reprobe children when a new driver is added to uhub o fix the usbd_probe_and_attach to set the ivars to a malloc'd area, as well as freeing the ivars on child destruction. o Don't delete children that don't attach. Evidentally, the need to do this is a common misconception. o minor formatting foo that may violate style(9) at the moment, but keeps the diffs against my p4 tree smaller. This does not solve the ugen gobbling things up problem, but the fixes I have for that expose bugs in other parts of the tree...
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r--sys/dev/usb/usb_subr.c68
1 files changed, 31 insertions, 37 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 52e363d..3f50e63 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -853,20 +853,22 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
#if defined(__FreeBSD__)
- /*
- * XXX uaa is a static var. Not a problem as it _should_ be used only
- * during probe and attach. Should be changed however.
- */
- device_t bdev;
+ /* XXX FreeBSD may leak resources on failure cases -- fixme */
+ device_t bdev;
+ struct usb_attach_arg *uaap;
+
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
- printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
- return (USBD_INVAL);
+ device_printf(parent, "Device creation failed\n");
+ return (USBD_INVAL);
}
- device_set_ivars(bdev, &uaa);
device_quiet(bdev);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ return (USBD_INVAL);
+ }
+ device_set_ivars(bdev, uaap);
#endif
-
uaa.device = dev;
uaa.iface = NULL;
uaa.ifaces = NULL;
@@ -888,15 +890,14 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
return (USBD_NOMEM);
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
if (dv) {
return (USBD_NORMAL_COMPLETION);
- } else {
- tmpdv = dev->subdevs;
- dev->subdevs = NULL;
- free(tmpdv, M_USB);
}
-
+ tmpdv = dev->subdevs;
+ dev->subdevs = NULL;
+ free(tmpdv, M_USB);
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
@@ -915,10 +916,6 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
printf("%s: port %d, set config at addr %d failed\n",
USBDEVPTRNAME(parent), port, addr);
#endif
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
-
return (err);
}
nifaces = dev->cdesc->bNumInterface;
@@ -929,18 +926,11 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
uaa.nifaces = nifaces;
dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
if (dev->subdevs == NULL) {
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NOMEM);
}
dev->ifacenums = malloc((nifaces) * sizeof(*dev->ifacenums),
M_USB,M_NOWAIT);
if (dev->ifacenums == NULL) {
- free(tmpdv, M_USB);
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NOMEM);
}
@@ -953,6 +943,7 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
dev->subdevs[found] = bdev;
dev->subdevs[found + 1] = 0;
dev->ifacenums[found] = i;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
usbd_submatch);
if (dv != NULL) {
@@ -963,11 +954,15 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
/* create another child for the next iface */
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
- printf("%s: Device creation failed\n",
- USBDEVNAME(dev->bus->bdev));
+ device_printf(parent,
+ "Device add failed\n");
return (USBD_NORMAL_COMPLETION);
}
- device_set_ivars(bdev, &uaa);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ return (USBD_NOMEM);
+ }
+ device_set_ivars(bdev, uaap);
device_quiet(bdev);
#endif
} else {
@@ -976,8 +971,9 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
}
if (found != 0) {
#if defined(__FreeBSD__)
- /* remove the last created child again; it is unused */
+ /* remove the last created child. It is unused */
device_delete_child(parent, bdev);
+ /* free(uaap, M_USB); */ /* May be needed? xxx */
#endif
return (USBD_NORMAL_COMPLETION);
}
@@ -1000,18 +996,19 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
uaa.configno = UHUB_UNK_CONFIGURATION;
uaa.ifaceno = UHUB_UNK_INTERFACE;
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0)
+ if (dev->subdevs == 0) {
return (USBD_NOMEM);
+ }
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
+ *uaap = uaa;
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
if (dv != NULL) {
return (USBD_NORMAL_COMPLETION);
- } else {
- tmpdv = dev->subdevs;
- dev->subdevs = 0;
- free(tmpdv, M_USB);
}
+ tmpdv = dev->subdevs;
+ dev->subdevs = 0;
+ free(tmpdv, M_USB);
/*
* The generic attach failed, but leave the device as it is.
@@ -1019,9 +1016,6 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev,
* fully operational and not harming anyone.
*/
DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
return (USBD_NORMAL_COMPLETION);
}
OpenPOWER on IntegriCloud